<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<!--[if lt IE 9]>
  <script src="https://oss.maxcdn.com/libs/html5shiv/3.7.0/html5shiv.js"></script>
<![endif]-->
<title>VIM 中文帮助: 表达式求值，条件执行命令</title>
<link rel="stylesheet" href="vim-stylesheet.css" type="text/css" />
<link rel="canonical" href="https://yianwillis.github.io/vimcdoc/doc/eval.html" />
<script type="text/javascript" src="vimcdoc.js"></script>
<meta name="viewport" content="width=device-width, initial-scale=1" />
</head>
<body>
<nav id=banner>
<form action=tags.html target="tag_iframe">
  <input type="text" name="tag" id="tag" placeholder="标签搜索">
</form>
<iframe name="tag_iframe" src=""></iframe>
<a href="help.html">帮助总览</a> &middot;
<hr/>
<a href="quickref.html">快速参考</a> &middot;
<a href="index.html">命令索引</a> &middot;
<a href="eval.html#functions">函数列表</a> &middot;
<a href="quickref.html#option-list">选项列表</a> &middot;
<hr/>
<a href="usr_toc.html">用户手册</a> &middot;
<a href="help.html#reference_toc">参考手册</a> &middot;
</nav>

<header>
<h2>eval</h2>
</header>
<article id=outer>
<section class=inner>
<b class="vimtag"> <a name="eval.txt">eval.txt</a> </b>      适用于 Vim 9.0 版本。   最近更新: 2023年2月


                  <code class="vim">VIM 参考手册    by Bram Moolenaar</code>
                                <code class="vim">译者</code>: Willis


表达式求值                              <b class="vimtag"> <a name="expression">expression</a> </b> <b class="vimtag"> <a name="expr">expr</a> </b> <b class="vimtag"> <a name="E15">E15</a> </b> <b class="vimtag"> <a name="eval">eval</a> </b>
                                                        <b class="vimtag"> <a name="E1002">E1002</a> </b>
用户手册第 41 章  <a href="usr_41.html#usr_41.txt">usr_41.txt</a>  有使用表达式的介绍。

<code class="note">注意</code>: 表达式求值可以在编译时关闭。如果你这么做，本文档介绍的特性就不复存在。见
 <a href="various.html#+eval">+eval</a>  和  <a href="eval.html#no-eval-feature">no-eval-feature</a> 。

此文件主要介绍后向兼容 (老式) 的 Vim 脚本。关于执行快很多、支持类型检查还有更
多优点的 Vim9 脚本的特性，参见  <a href="vim9.html#vim9.txt">vim9.txt</a> 。两者语法和语义有不同时，会给出说
明。

1.  变量                 <a href="eval.html#variables">variables</a> 
    1.1 变量类型
    1.2 函数引用                 <a href="eval.html#Funcref">Funcref</a> 
    1.3 列表                     <a href="eval.html#Lists">Lists</a> 
    1.4 字典                     <a href="eval.html#Dictionaries">Dictionaries</a> 
    1.5 blob                     <a href="eval.html#Blobs">Blobs</a> 
    1.6 变量的更多细节           <a href="eval.html#more-variables">more-variables</a> 
2.  表达式语法           <a href="eval.html#expression-syntax">expression-syntax</a> 
3.  内部变量             <a href="eval.html#internal-variables">internal-variables</a> 
4.  内建函数             <a href="eval.html#functions">functions</a> 
5.  定义函数             <a href="eval.html#user-functions">user-functions</a> 
6.  花括号名字           <a href="eval.html#curly-braces-names">curly-braces-names</a> 
7.  命令                 <a href="eval.html#expression-commands">expression-commands</a> 
8.  例外处理             <a href="eval.html#exception-handling">exception-handling</a> 
9.  示例                 <a href="eval.html#eval-examples">eval-examples</a> 
10. Vim 脚本版本         <a href="eval.html#vimscript-version">vimscript-version</a> 
11. 不包含 +eval 特性    <a href="eval.html#no-eval-feature">no-eval-feature</a> 
12. 沙盘 (sandbox)       <a href="eval.html#eval-sandbox">eval-sandbox</a> 
13. 文本锁               <a href="eval.html#textlock">textlock</a> 

测试支持的文档可见  <a href="testing.html#testing.txt">testing.txt</a> 。
剖视的文档可见  <a href="repeat.html#profiling">profiling</a> 。

</section><hr class="doubleline" /><section class=inner>
<h4>1. 变量                                                 <b class="vimtag"> <a name="variables">variables</a> </b></h4>
<code class="section">1.1 变量类型 </code>
                                        <b class="vimtag"> <a name="E712">E712</a> </b> <b class="vimtag"> <a name="E896">E896</a> </b> <b class="vimtag"> <a name="E897">E897</a> </b> <b class="vimtag"> <a name="E899">E899</a> </b> <b class="vimtag"> <a name="E1098">E1098</a> </b>
                                        <b class="vimtag"> <a name="E1107">E1107</a> </b> <b class="vimtag"> <a name="E1135">E1135</a> </b> <b class="vimtag"> <a name="E1138">E1138</a> </b>
有十种类型的变量:

                                                        <b class="vimtag"> <a name="Number">Number</a> </b> <b class="vimtag"> <a name="Integer">Integer</a> </b>
数值            32 位或 64 位带符号整数。 <a href="eval.html#expr-number">expr-number</a> 
                位数可以  <a href="eval.html#v:numbersize">v:numbersize</a>  得到。
                示例:  -123  0x10  0o177  0b1011

浮点数          带小数的数值。 <a href="eval.html#floating-point-format">floating-point-format</a>  <b class="vimtag"> <a name="Float">Float</a> </b>
                示例: 123.456  1.15e-6  -1.1e3

字符串          NUL 结尾的 8 位无符号字符 (即字节) 的串。 <a href="eval.html#expr-string">expr-string</a> 
                示例: "ab\txx\"--"  'x-z''a,c'

列表            项目的有序的序列，详见  <a href="eval.html#List">List</a> 。
                示例: [1, 2, ['a', 'b']]

字典            关联的无序数组: 每个项目包含一个键和一个值。 <a href="eval.html#Dictionary">Dictionary</a> 
                示例:
                        {<code class="badlink">'blue'</code>: "#0000ff", <code class="badlink">'red'</code>: "#ff0000"}
                        #{blue: "#0000ff", red: "#ff0000"}

函数引用        指向一个函数的引用  <a href="eval.html#Funcref">Funcref</a> 。
                示例: function("strlen")
                可以绑定到字典或参数上，这样就类似于一个偏函数。
                示例: function("Callback", <code class="special">[arg]</code>, myDict)

特殊             <a href="eval.html#v:false">v:false</a> 、 <a href="eval.html#v:true">v:true</a> 、 <a href="eval.html#v:none">v:none</a>  和  <a href="eval.html#v:null">v:null</a> 。 <b class="vimtag"> <a name="Special">Special</a> </b>

作业            用于作业，见  <a href="channel.html#job_start()">job_start()</a> 。 <b class="vimtag"> <a name="Job">Job</a> </b> <b class="vimtag"> <a name="Jobs">Jobs</a> </b>

通道            用于通道，见  <a href="channel.html#ch_open()">ch_open()</a> 。 <b class="vimtag"> <a name="Channel">Channel</a> </b> <b class="vimtag"> <a name="Channels">Channels</a> </b>

blob            二进制大对象 (Binary Large Object)。存储任意字符序列。详见
                 <a href="eval.html#Blob">Blob</a> 
                示例: 0zFF00ED015DAF
                0z 是空 blob。


数值和字符串类型之间会根据使用的情况自动转换。

数值到字符串的转换使用数值的 ASCII 表示。例如:
<code class="section">        数值 123        --&gt;     字符串 "123" </code>
<code class="section">        数值 0          --&gt;     字符串 "0" </code>
<code class="section">        数值 -1         --&gt;     字符串 "-1" </code>
                                                        <b class="vimtag"> <a name="octal">octal</a> </b>
只在老式 Vim 脚本中进行字符串到数值的转换，Vim9 脚本不进行转换。转换时，把字符
串开头的一系列数字位转换成数值。可以识别十六进制 "0xf9"、八进制 "017" 或
"0o17" 和二进制 "0b10" 形式的数值
<code class="note">注意</code>:  <a href="vim9.html#Vim9">Vim9</a>  脚本或  <a href="eval.html#scriptversion-4">scriptversion-4</a>  里不识别 "0" 开头的八进制。0o 记法需要
8.2.0886 补丁。
如果字符串不以数字开始，则结果为零。
例如:
<code class="section">        字符串 "456"    --&gt;     数值 456 </code>
<code class="section">        字符串 "6bar"   --&gt;     数值 6 </code>
<code class="section">        字符串 "foo"    --&gt;     数值 0 </code>
<code class="section">        字符串 "0xf1"   --&gt;     数值 241 </code>
<code class="section">        字符串 "0100"   --&gt;     数值 64 </code>
<code class="section">        字符串 "0b101"  --&gt;     数值 5 </code>
<code class="section">        字符串 "-8"     --&gt;     数值 -8 </code>
<code class="section">        字符串 "+8"     --&gt;     数值 0 </code>

要强制从字符串转换到数值，给它加零: 
<code class="example">        :echo "0100" + 0</code>
<code class="section">        64 </code>

要避免开头的零导致八进制的转换，或者想换不同的基底，用  <a href="builtin.html#str2nr()">str2nr()</a> 。

                                                <b class="vimtag"> <a name="TRUE">TRUE</a> </b> <b class="vimtag"> <a name="FALSE">FALSE</a> </b> <b class="vimtag"> <a name="Boolean">Boolean</a> </b>
布尔型的操作使用数值类型。零代表假值 (FALSE)，非零代表真值 (TRUE)。也可用
 <a href="eval.html#v:false">v:false</a>  和  <a href="eval.html#v:true">v:true</a> ，Vim9 脚本中可用  <a href="vim9.html#false">false</a>  和  <a href="vim9.html#true">true</a> 。函数返回 TRUE 时相当
于数值一，FALSE 相当于数值零。

<code class="note">注意</code> 在命令: 
<code class="example">        :if "foo"</code>
<code class="example">        :" _不_ 执行</code>
里，"foo" 被转换成 0，也就是假值。如果字符串以非零数字开始，则代表真值: 
<code class="example">        :if "8foo"</code>
<code class="example">        :" 执行</code>
要测试字符串非空，应该使用 empty(): 
<code class="example">        :if !empty("foo")</code>
<code class="example"></code>
                                                <b class="vimtag"> <a name="falsy">falsy</a> </b> <b class="vimtag"> <a name="truthy">truthy</a> </b>
表达式可用作条件，这里忽略类型，而仅仅判断该值是 "某种程序是真的" 或 "某种程度
是假的"。准假值 (falsy) 为:
        数值零
        空字符串、blob、列表或字典
其它值均为准真值 (truthy)。例如:
        0       准假值
        1       准真值
        -1      准真值
        0.0     准假值
        0.1     准真值
        ''      准假值
        'x'     准真值
        []      准假值
        <code class="special">[0]</code>     准真值
        <code class="special">{}</code>      准假值
        #{x: 1} 准真值
        0z      准假值
        0z00    准真值

                                                        <b class="vimtag"> <a name="non-zero-arg">non-zero-arg</a> </b>
函数参数和  <a href="eval.html#TRUE">TRUE</a>  行为通常略有差异: 如果参数存在且其值为非零数值、 <a href="eval.html#v:true">v:true</a>  或
非空字符串，则视之为真值。
<code class="note">注意</code> " " 和 "0" 也是非空字符串，亦应视为真值。列表、字典和浮点数不是数值或字符
串，因而视为假值。

                <b class="vimtag"> <a name="E611">E611</a> </b> <b class="vimtag"> <a name="E745">E745</a> </b> <b class="vimtag"> <a name="E728">E728</a> </b> <b class="vimtag"> <a name="E703">E703</a> </b> <b class="vimtag"> <a name="E729">E729</a> </b> <b class="vimtag"> <a name="E730">E730</a> </b> <b class="vimtag"> <a name="E731">E731</a> </b> <b class="vimtag"> <a name="E908">E908</a> </b> <b class="vimtag"> <a name="E910">E910</a> </b>
                <b class="vimtag"> <a name="E913">E913</a> </b> <b class="vimtag"> <a name="E974">E974</a> </b> <b class="vimtag"> <a name="E975">E975</a> </b> <b class="vimtag"> <a name="E976">E976</a> </b> <b class="vimtag"> <a name="E1319">E1319</a> </b> <b class="vimtag"> <a name="E1320">E1320</a> </b> <b class="vimtag"> <a name="E1321">E1321</a> </b> <b class="vimtag"> <a name="E1322">E1322</a> </b>
                <b class="vimtag"> <a name="E1323">E1323</a> </b> <b class="vimtag"> <a name="E1324">E1324</a> </b>
 <a href="eval.html#List">List</a> 、 <a href="eval.html#Dictionary">Dictionary</a> 、 <a href="eval.html#Funcref">Funcref</a> 、 <a href="eval.html#Job">Job</a> 、 <a href="eval.html#Channel">Channel</a> 、 <a href="eval.html#Blob">Blob</a> 、 <a href="vim9class.html#Class">Class</a>  和  <a href="vim9class.html#object">object</a> 
类型不会自动进行转换。

                                                        <b class="vimtag"> <a name="E805">E805</a> </b> <b class="vimtag"> <a name="E806">E806</a> </b> <b class="vimtag"> <a name="E808">E808</a> </b>
混合数值和浮点数的计算时，数值转换为浮点数。否则没有自动到浮点数的转换。用
str2float() 可转换字符串到浮点数，printf() 从浮点数到字符串，float2nr() 则从浮
点数到数值。

                        <b class="vimtag"> <a name="E362">E362</a> </b> <b class="vimtag"> <a name="E891">E891</a> </b> <b class="vimtag"> <a name="E892">E892</a> </b> <b class="vimtag"> <a name="E893">E893</a> </b> <b class="vimtag"> <a name="E894">E894</a> </b> <b class="vimtag"> <a name="E907">E907</a> </b> <b class="vimtag"> <a name="E911">E911</a> </b> <b class="vimtag"> <a name="E914">E914</a> </b>
期待浮点数的地方也可用数值代替，但其它都不行。

                                                <b class="vimtag"> <a name="no-type-checking">no-type-checking</a> </b>
试图改变变量类型不会报错。


<code class="section">1.2 函数引用 </code>
                                        <b class="vimtag"> <a name="Funcref">Funcref</a> </b> <b class="vimtag"> <a name="E695">E695</a> </b> <b class="vimtag"> <a name="E718">E718</a> </b> <b class="vimtag"> <a name="E1192">E1192</a> </b>
函数引用变量可以通过  <a href="builtin.html#function()">function()</a>  函数、 <a href="builtin.html#funcref()">funcref()</a>  函数、( <a href="vim9.html#Vim9">Vim9</a>  脚本里) 函数
名、或者  <a href="eval.html#expr-lambda">expr-lambda</a>  匿名表达式得到。可以在表达式里用它来代替函数名，在围绕
参数的括号之前，以调用它引用的函数。 <a href="vim9.html#Vim9">Vim9</a>  脚本示例: 
<code class="example"></code>
<code class="example">        :var Fn = MyFunc</code>
<code class="example">        :echo Fn()</code>
<code class="example"></code>
老式脚本: 
<code class="example">        :let Fn = function("MyFunc")</code>
<code class="example">        :echo Fn()</code>
                                                        <b class="vimtag"> <a name="E704">E704</a> </b> <b class="vimtag"> <a name="E705">E705</a> </b> <b class="vimtag"> <a name="E707">E707</a> </b>
函数引用变量必须以大写字母、"s:"、"w:"、"t:" 或 "b:" 开始。可以用 "g:"，但后面
的名字必须以大写开始。函数引用变量不能和任何函数重名。

特例是可以定义函数并直接把它的函数引用赋给字典的一个项目。例如: 
<code class="example">        :function dict.init() dict</code>
<code class="example">        :   let self.val = 0</code>
<code class="example">        :endfunction</code>
<code class="example"></code>
该字典的键可以用小写字母开始。这里不用实际的函数名。另见  <a href="eval.html#numbered-function">numbered-function</a> 。

函数引用可以用  <a href="userfunc.html#:call">:call</a>  命令调用: 
<code class="example">        :call Fn()</code>
<code class="example">        :call dict.init()</code>
<code class="example"></code>
所引用的函数的名字可以用  <a href="builtin.html#string()">string()</a>  得到， 
<code class="example">        :let func = string(Fn)</code>
<code class="example"></code>
你可以用  <a href="builtin.html#call()">call()</a>  来调用函数引用并用一个列表变量来传递参数: 
<code class="example">        :let r = call(Fn, mylist)</code>

                                                                <b class="vimtag"> <a name="Partial">Partial</a> </b>
函数引用可以选择绑定字典和/或参数，也叫偏函数。通过向 function() 或 funcref()
提供字典和/或参数完成。调用函数时，该字典和/或参数被传入函数。例如: 
<code class="example"></code>
<code class="example">        let Cb = function('Callback', ['foo'], myDict)</code>
<code class="example">        call Cb('bar')</code>
<code class="example"></code>
这类似于如下方式地调用函数: 
<code class="example">        call myDict.Callback('foo', 'bar')</code>
<code class="example"></code>
对  <a href="channel.html#ch_open()">ch_open()</a>  这样传递函数作为参数的情况，这很有用。

<code class="note">注意</code> 把函数作为字典的一个成员时，也会绑定函数到字典: 
<code class="example"></code>
<code class="example">        let myDict.myFunction = MyFunction</code>
<code class="example">        call myDict.myFunction()</code>
<code class="example"></code>
这里，调用 "myFunction" 成员时，MyFunction() 会通过 "self" 得到 myDict。如果把
"myFunction" 赋给 otherDict 并调用之，则相应绑定到 otherDict 上: 
<code class="example"></code>
<code class="example">        let otherDict.myFunction = myDict.myFunction</code>
<code class="example">        call otherDict.myFunction()</code>
<code class="example"></code>
现在 "self" 变成了 "otherDict"。但字典如果是显式绑定，这不会发生: 
<code class="example"></code>
<code class="example">        let myDict.myFunction = function(MyFunction, myDict)</code>
<code class="example">        let otherDict.myFunction = myDict.myFunction</code>
<code class="example">        call otherDict.myFunction()</code>
<code class="example"></code>
这里 "self" 还是 "myDict"，因为是通过显式绑定的。


<code class="section">1.3 列表 </code>
                                                <b class="vimtag"> <a name="list">list</a> </b> <b class="vimtag"> <a name="List">List</a> </b> <b class="vimtag"> <a name="Lists">Lists</a> </b> <b class="vimtag"> <a name="E686">E686</a> </b>
列表是项目的有序序列。项目可以是任何类型，用索引号可以进行访问。可以在序列的任
何位置上增加或者删除项目。


<code class="section">列表建立 </code>
                                                        <b class="vimtag"> <a name="E696">E696</a> </b> <b class="vimtag"> <a name="E697">E697</a> </b>
列表用方括号里逗号分隔的项目序列建立。例如: 
<code class="example">        :let mylist = [1, two, 3, "four"]</code>
<code class="example">        :let emptylist = []</code>
<code class="example"></code>
项目可以是任何表达式。用列表作为项目就能建立列表的列表: 
<code class="example">        :let nestlist = [[11, 12], [21, 22], [31, 32]]</code>
<code class="example"></code>
忽略末项之后额外的逗号。


<code class="section">列表索引 </code>
                                                        <b class="vimtag"> <a name="list-index">list-index</a> </b> <b class="vimtag"> <a name="E684">E684</a> </b>
在列表之后的方括号中放上索引号可以访问列表项目。索引从零开始，也就是说，第一个
项目的索引值为零。 
<code class="example">        :let item = mylist[0]           " 得到第一个项目: 1</code>
<code class="example">        :let item = mylist[2]           " 得到第三个项目: 3</code>
<code class="example"></code>
如果返回的项目本身是列表，可以重复这样的操作: 
<code class="example">        :let item = nestlist[0][1]      " 得到第一个列表的第二个项目: 12</code>

负索引从尾端开始计算。索引 -1 指向列表的最后一个项目，-2 指向倒数第二个项目，
依此类推。 
<code class="example">        :let last = mylist[-1]          " 得到最后一个项目: "four"</code>
<code class="example"></code>
要避免非法索引值产生的错误，用  <a href="builtin.html#get()">get()</a>  函数。如果项目不存在，它返回零或者你指
定的缺省值: 
<code class="example">        :echo get(mylist, idx)</code>
<code class="example">        :echo get(mylist, idx, "NONE")</code>
<code class="example"></code>
<code class="example"></code>
<code class="section">列表连接 </code>
                                                        <b class="vimtag"> <a name="list-concatenation">list-concatenation</a> </b>
两个列表可以用 "+" 操作符连接: 
<code class="example">        :let longlist = mylist + [5, 6]</code>
<code class="example">        :let mylist += [7, 8]</code>
<code class="example"></code>
要在前面或后面附加项目，在项目外面加上 [] 从而把它变为一个列表。要改变列表内部
的值，见下  <a href="eval.html#list-modification">list-modification</a> 。


<code class="section">子列表</code>
                                                        <b class="vimtag"> <a name="sublist">sublist</a> </b>
列表的一部分可以通过指定首末两个索引获得，方括号内以冒号分隔两者: 
<code class="example">        :let shortlist = mylist[2:-1]   " 得到列表 [3, "four"]</code>
<code class="example"></code>
首索引的省略类似于用 0。末索引的省略类似于用 -1。 
<code class="example">        :let endlist = mylist[2:]       " 从项目 2 到结束: [3, "four"]</code>
<code class="example">        :let shortlist = mylist[2:2]    " 单个项目的列表: [3]</code>
<code class="example">        :let otherlist = mylist[:]      " 复制列表</code>
<code class="example"></code>
<code class="note">注意</code>末索引是闭的。如果希望用开的索引，可用  <a href="builtin.html#slice()">slice()</a>  方法。

如果首索引在列表末项之后或者末索引小于首索引，返回空列表。没有错误信息。

如果末索引大于等于列表的长度，使用列表长度减一: 
<code class="example">        :let mylist = [0, 1, 2, 3]</code>
<code class="example">        :echo mylist[2:8]               " 返回: [2, 3]</code>

<code class="note">注意</code>: mylist[s:e] 意味着用变量 "s:e" 作为索引。在 ":" 之前用单个字母作为变量要
小心。需要的话加上空格: mylist[s : e]。


<code class="section">列表同一 </code>
                                                        <b class="vimtag"> <a name="list-identity">list-identity</a> </b>
如果变量 "aa" 是列表，把它赋给另一个变量 "bb" 后，两个变量指向同一列表。因此，
对列表 "aa" 的修改也同时修改了 "bb": 
<code class="example">        :let aa = [1, 2, 3]</code>
<code class="example">        :let bb = aa</code>
<code class="example">        :call add(aa, 4)</code>
<code class="example">        :echo bb</code>
        [1, 2, 3, 4]

 <a href="builtin.html#copy()">copy()</a>  函数可以复制列表。如上所述，用 [:] 也可。这种方式建立列表的浅备份: 改
变列表中的列表项目仍然会修改复制列表的相应项目: 
<code class="example">        :let aa = [[1, 'a'], 2, 3]</code>
<code class="example">        :let bb = copy(aa)</code>
<code class="example">        :call add(aa, 4)</code>
<code class="example">        :let aa[0][1] = 'aaa'</code>
<code class="example">        :echo aa</code>
        [[1, aaa], 2, 3, 4] 
<code class="example">        :echo bb</code>
        [[1, aaa], 2, 3]

要建立一个完全独立的列表，用  <a href="builtin.html#deepcopy()">deepcopy()</a> 。它递归地建立列表值的备份。最深可达
100 层。

可用操作符 "is" 检查两个变量是否指向同一个列表。"isnot" 刚好相反。与此对照，
"==" 比较两个列表的值是否相同。 
<code class="example">        :let alist = [1, 2, 3]</code>
<code class="example">        :let blist = [1, 2, 3]</code>
<code class="example">        :echo alist is blist</code>
        0 
<code class="example">        :echo alist == blist</code>
        1

比较列表时 <code class="note">注意</code>: 如果长度相同，所有项目用 "==" 的比较的结果也相同，两个列表就
认为相同。有一个例外: 数值和字符串总被认为不相同。这里不进行自动类型转换，而在
变量间直接用 "==" 却不是如此。例如: 
<code class="example">        echo 4 == "4"</code>
        1 
<code class="example">        echo [4] == ["4"]</code>
        0

因此可以说，列表的比较比数值和字符串的比较更严格。你同样可以用这种方式比较简单
类型的值，把它们放到列表里就行了: 
<code class="example"></code>
<code class="example">        :let a = 5</code>
<code class="example">        :let b = "5"</code>
<code class="example">        :echo a == b</code>
        1 
<code class="example">        :echo [a] == [b]</code>
        0


<code class="section">列表解包 </code>

要给列表项目解包，即把它们分别存入单独的变量，用方括号把变量括起来，如同把它们
当作列表项目: 
<code class="example">        :let [var1, var2] = mylist</code>
<code class="example"></code>
如果变量和列表的项目数量不同，报错。要处理列表中所有额外的项目，加上 ";" 和单
个变量: 
<code class="example">        :let [var1, var2; rest] = mylist</code>
<code class="example"></code>
它的工作方式就像: 
<code class="example">        :let var1 = mylist[0]</code>
<code class="example">        :let var2 = mylist[1]</code>
<code class="example">        :let rest = mylist[2:]</code>
<code class="example"></code>
如果只有两个项目，不会报错。这时 "rest" 成为空表。


<code class="section">列表修改 </code>
                                                        <b class="vimtag"> <a name="list-modification">list-modification</a> </b>
要修改列表的指定项目，用  <a href="eval.html#:let">:let</a> : 
<code class="example">        :let list[4] = "four"</code>
<code class="example">        :let listlist[0][3] = item</code>
<code class="example"></code>
要修改列表的一部分，可以指定要修改的首末项目。提供的值的个数必须不少于该范围内
的项目数: 
<code class="example">        :let list[3:5] = [3, 4, 5]</code>
<code class="example"></code>
给列表增加和删除项目可以通过函数完成。一些例子如下: 
<code class="example">        :call insert(list, 'a')         " 在最前面插入 'a'</code>
<code class="example">        :call insert(list, 'a', 3)      " 在 list[3] 前插入项目 'a'</code>
<code class="example">        :call add(list, "new")          " 在最后附加字符串项目</code>
<code class="example">        :call add(list, [1, 2])         " 在最后附加新的列表项目</code>
<code class="example">        :call extend(list, [1, 2])      " 在最后扩展列表，使之多包含两个项目</code>
<code class="example">        :let i = remove(list, 3)        " 删除项目 3</code>
<code class="example">        :unlet list[3]                  " 同上</code>
<code class="example">        :let l = remove(list, 3, -1)    " 从项目 3 删除到最后</code>
<code class="example">        :unlet list[3 : ]               " 同上</code>
<code class="example">        :call filter(list, 'v:val !~ "x"')  " 删除有 'x' 的项目</code>
<code class="example"></code>
改变列表项目的顺序: 
<code class="example">        :call sort(list)                " 按字母给列表排序</code>
<code class="example">        :call reverse(list)             " 反转项目的顺序</code>
<code class="example">        :call uniq(sort(list))          " 排序并删除重复项</code>
<code class="example"></code>
<code class="example"></code>
<code class="section">For 循环 </code>

 <a href="eval.html#:for">:for</a>  循环为每个列表、字符串或 Blob 中的项目执行命令。一个变量被依次设为每个
列表项目。例如: 
<code class="example">        :for item in mylist</code>
<code class="example">        :   call Doit(item)</code>
<code class="example">        :endfor</code>
<code class="example"></code>
它的工作方式就像: 
<code class="example">        :let index = 0</code>
<code class="example">        :while index &lt; len(mylist)</code>
<code class="example">        :   let item = mylist[index]</code>
<code class="example">        :   :call Doit(item)</code>
<code class="example">        :   let index = index + 1</code>
<code class="example">        :endwhile</code>
<code class="example"></code>
如果你只是想要修改每个列表项目， <a href="builtin.html#map()">map()</a>  函数比 for 循环简单得多。

就像  <a href="eval.html#:let">:let</a>  命令， <a href="eval.html#:for">:for</a>  也可以接受变量的列表。这需要参数是列表的列表。 
<code class="example">        :for [lnum, col] in [[1, 3], [2, 8], [3, 0]]</code>
<code class="example">        :   call Doit(lnum, col)</code>
<code class="example">        :endfor</code>
<code class="example"></code>
这就像对列表的每个项目使用了  <a href="eval.html#:let">:let</a>  命令。重复一次，类型必须相同，否则会报错。

也可以用变量保存列表变量的其余项目: 
<code class="example">        :for [i, j; rest] in listlist</code>
<code class="example">        :   call Doit(i, j)</code>
<code class="example">        :   if !empty(rest)</code>
<code class="example">        :      echo "remainder: " .. string(rest)</code>
<code class="example">        :   endif</code>
<code class="example">        :endfor</code>
<code class="example"></code>
对 Blob 而言，每次访问一个字节。

对字符串而言，每次访问一个字符，包含组合字符在内。例如: 
<code class="example">        for c in text</code>
<code class="example">          echo 'This character is ' .. c</code>
<code class="example">        endfor</code>
<code class="example"></code>
<code class="example"></code>
<code class="section">列表的相关函数 </code>
                                                <b class="vimtag"> <a name="E714">E714</a> </b>
可用于列表的函数: 
<code class="example">        :let r = call(funcname, list)   " 调用带参数列表的函数</code>
<code class="example">        :if empty(list)                 " 检查 list 是否为空</code>
<code class="example">        :let l = len(list)              " list 项目的数量</code>
<code class="example">        :let big = max(list)            " list 项目的最大值</code>
<code class="example">        :let small = min(list)          " list 项目的最小值</code>
<code class="example">        :let xs = count(list, 'x')      " 计算 list 里 'x' 出现的次数</code>
<code class="example">        :let i = index(list, 'x')       " list 第一个 'x' 的位置</code>
<code class="example">        :let lines = getline(1, 10)     " 得到缓冲区十行文本行</code>
<code class="example">        :call append('$', lines)        " 附加若干文本行到缓冲区尾部</code>
<code class="example">        :let list = split("a b c")      " 用字符串中的项目建立列表</code>
<code class="example">        :let string = join(list, ', ')  " 用 list 项目构造字符串</code>
<code class="example">        :let s = string(list)           " list 的字符串表示</code>
<code class="example">        :call map(list, '"&gt;&gt; " .. v:val')  " 在每个项目前加上 "&gt;&gt; "</code>
<code class="example"></code>
不要忘记组合使用不同功能可以简化任务。例如，要计算列表中所有数值的总和: 
<code class="example">        :exe 'let sum = ' .. join(nrlist, '+')</code>
<code class="example"></code>
<code class="example"></code>
<code class="section">1.4 字典 </code>
                                <b class="vimtag"> <a name="dict">dict</a> </b> <b class="vimtag"> <a name="Dict">Dict</a> </b> <b class="vimtag"> <a name="Dictionaries">Dictionaries</a> </b> <b class="vimtag"> <a name="Dictionary">Dictionary</a> </b>
字典是关联数组: 每个项目有一个键和一个值。用键可以定位项目，而项目的存储不能确
定任何特定顺序。


<code class="section">字典建立 </code>
                                                <b class="vimtag"> <a name="E720">E720</a> </b> <b class="vimtag"> <a name="E721">E721</a> </b> <b class="vimtag"> <a name="E722">E722</a> </b> <b class="vimtag"> <a name="E723">E723</a> </b>
字典通过花括号里逗号分隔的项目列表建立。每个项目包含以冒号分隔的键和值。一个键
只能出现一次。例如: 
<code class="example">        :let mydict = {1: 'one', 2: 'two', 3: 'three'}</code>
<code class="example">        :let emptydict = {}</code>
                                                        <b class="vimtag"> <a name="E713">E713</a> </b> <b class="vimtag"> <a name="E716">E716</a> </b> <b class="vimtag"> <a name="E717">E717</a> </b>
键必须是字符串。用数值也可以，但它总被自动转换为字符串。所以字符串 '4' 和数值
4 总会找到相同的项目。<code class="note">注意</code> 字符串 '04' 和数值 04 是不一样的，因为后者被转换成
字符串 '4'，前导的零会丢掉。空字符串也可用作键。

 <a href="vim9.html#Vim9">Vim9</a>  脚本里，只包含字母数字、下划线和连字符的键可按本义出现，见
 <a href="vim9.html#vim9-literal-dict">vim9-literal-dict</a> 。
                                                <b class="vimtag"> <a name="literal-Dict">literal-Dict</a> </b> <b class="vimtag"> <a name="%23{}">#{}</a> </b>
要不想给每个键都围上引号，老式脚本里可以用 #<code class="special">{}</code> 形式。这要求键只包含 ASCII 字
母、数位、'-' 和 '_'。例如: 
<code class="example">        :let mydict = #{zero: 0, one_key: 1, two-key: 2, 333: 3}</code>
<code class="note">注意</code> 这里的 333 代表字符串 "333"。空键不能用 #<code class="special">{}</code> 表示。
 <a href="vim9.html#Vim9">Vim9</a>  脚本不能使用 #<code class="special">{}</code> 形式，因为它和注释的头部会发生混淆。

值可以是任何表达式。如果值本身是字典，就可以建立嵌套的字典: 
<code class="example">        :let nestdict = {1: {11: 'a', 12: 'b'}, 2: {21: 'c'}}</code>
<code class="example"></code>
忽略末项之后的逗号。


<code class="section">访问项目 </code>

常见的访问项目的方式是把键放入方括号: 
<code class="example">        :let val = mydict["one"]</code>
<code class="example">        :let mydict["four"] = 4</code>
<code class="example"></code>
用这种方式可以给已存在的字典增加新项目，这和列表不同。

如果键只包含字母、数字和下划线，可以使用如下形式  <a href="eval.html#expr-entry">expr-entry</a> : 
<code class="example">        :let val = mydict.one</code>
<code class="example">        :let mydict.four = 4</code>
<code class="example"></code>
因为项目可以是包括列表和字典的任何类型，你可以反复使用索引和键进行访问: 
<code class="example">        :echo dict.key[idx].key</code>
<code class="example"></code>
<code class="example"></code>
<code class="section">字典到列表的转换 </code>

你可以循环遍历字典的所有项目。为此，你需要把字典转为列表，然后把它传递给
 <a href="eval.html#:for">:for</a> 。

通常，你期望遍历所有的键，用  <a href="builtin.html#keys()">keys()</a>  函数就可以了: 
<code class="example">        :for key in keys(mydict)</code>
<code class="example">        :   echo key .. ': ' .. mydict[key]</code>
<code class="example">        :endfor</code>
<code class="example"></code>
键列表没有经过排序。你可能希望先进行排序: 
<code class="example">        :for key in sort(keys(mydict))</code>
<code class="example"></code>
要遍历所有的值，用  <a href="builtin.html#values()">values()</a>  函数: 
<code class="example">        :for v in values(mydict)</code>
<code class="example">        :   echo "value: " .. v</code>
<code class="example">        :endfor</code>
<code class="example"></code>
如果你想同时得到键和值，用  <a href="builtin.html#items()">items()</a>  函数。它返回一个列表，其中每个项目是两个
项目的列表: 键和值: 
<code class="example">        :for [key, value] in items(mydict)</code>
<code class="example">        :   echo key .. ': ' .. value</code>
<code class="example">        :endfor</code>
<code class="example"></code>
<code class="example"></code>
<code class="section">字典同一 </code>
                                                        <b class="vimtag"> <a name="dict-identity">dict-identity</a> </b>
就像列表那样，你需要用  <a href="builtin.html#copy()">copy()</a>  和  <a href="builtin.html#deepcopy()">deepcopy()</a>  来构造字典的备份。否则，赋值产
生的结果会引用同一个字典: 
<code class="example">        :let onedict = {'a': 1, 'b': 2}</code>
<code class="example">        :let adict = onedict</code>
<code class="example">        :let adict['a'] = 11</code>
<code class="example">        :echo onedict['a']</code>
<code class="example">        11</code>
<code class="example"></code>
如果所有的键-值组对的比较结果相同，两个字典比较的结果也相同。详情见
 <a href="eval.html#list-identity">list-identity</a> 。


<code class="section">字典修改 </code>
                                                        <b class="vimtag"> <a name="dict-modification">dict-modification</a> </b>
要修改字典已经存在的项目或者增加新的项目，用  <a href="eval.html#:let">:let</a> : 
<code class="example">        :let dict[4] = "four"</code>
<code class="example">        :let dict['one'] = item</code>
<code class="example"></code>
从字典里删除项目可以通过  <a href="builtin.html#remove()">remove()</a>  或  <a href="eval.html#:unlet">:unlet</a>  完成。
从 dict 里删除键 "aaa" 的项目有三种方法: 
<code class="example">        :let i = remove(dict, 'aaa')</code>
<code class="example">        :unlet dict.aaa</code>
<code class="example">        :unlet dict['aaa']</code>
<code class="example"></code>
两个字典的合并可以用  <a href="builtin.html#extend()">extend()</a> : 
<code class="example">        :call extend(adict, bdict)</code>
这使得 adict 得到扩展，加入所有的 bdict 项目。对于重复的键，adict 项目被覆盖。
可选的第三个参数可以改变这一点。
<code class="note">注意</code> 这不影响字典项目的顺序，不要希望 ":echo adict" 会先显示原有 adict 项目，
然后再显示 bdict 的项目。

可用  <a href="builtin.html#filter()">filter()</a>  从字典里删除多个项目: 
<code class="example">        :call filter(dict, 'v:val =~ "x"')</code>
会删除 "dict" 里所有值不匹配 "x" 的项目。
也可这样来删除所有的项目: 
<code class="example">        call filter(dict, 0)</code>
<code class="example"></code>
有些情况下不允许删除或新增字典项目。特别是对所有项目进行遍历时。这种情况会给出
<b class="vimtag"> <a name="E1313">E1313</a> </b> 或其它错误。

<code class="section">字典函数 </code>
                                <b class="vimtag"> <a name="Dictionary-function">Dictionary-function</a> </b> <b class="vimtag"> <a name="self">self</a> </b> <b class="vimtag"> <a name="E725">E725</a> </b> <b class="vimtag"> <a name="E862">E862</a> </b>
定义函数时，如果带有 "dict" 属性，可以以一种特殊方式使用字典。例如: 
<code class="example">        :function Mylen() dict</code>
<code class="example">        :   return len(self.data)</code>
<code class="example">        :endfunction</code>
<code class="example">        :let mydict = {'data': [0, 1, 2, 3], 'len': function("Mylen")}</code>
<code class="example">        :echo mydict.len()</code>
<code class="example"></code>
这类似于面向对象编程的方法。字典项目用作  <a href="eval.html#Funcref">Funcref</a> 。局部变量 "self" 引用函数所
在的字典。 <a href="vim9.html#Vim9">Vim9</a>  脚本里可用类和对象，见  <a href="vim9class.html#:class">:class</a> 。

字典里也可以加入指向没有 "dict" 属性的函数的函数引用，不过这时无法使用 "self"
变量。

                                <b class="vimtag"> <a name="numbered-function">numbered-function</a> </b> <b class="vimtag"> <a name="anonymous-function">anonymous-function</a> </b>
要避免额外的函数名，可以定义时直接赋给字典: 
<code class="example">        :let mydict = {'data': [0, 1, 2, 3]}</code>
<code class="example">        :function mydict.len()</code>
<code class="example">        :   return len(self.data)</code>
<code class="example">        :endfunction</code>
<code class="example">        :echo mydict.len()</code>
<code class="example"></code>
该函数会得到一个编号，而 dict.len 的值是指向此函数的  <a href="eval.html#Funcref">Funcref</a> 。该函数只能通过
 <a href="eval.html#Funcref">Funcref</a>  访问。如果没有任何  <a href="eval.html#Funcref">Funcref</a>  引用，它会被自动删除。

编号函数不一定要有 "dict" 属性。

如果你的编号函数有错，可以用一个技巧知道它是什么内容。假定函数是 42，命令为: 
<code class="example"> :function g:42</code>
<code class="example"></code>
<code class="example"></code>
<code class="section">字典相关函数 </code>
                                                        <b class="vimtag"> <a name="E715">E715</a> </b>
可以用于字典的函数: 
<code class="example">        :if has_key(dict, 'foo')        " 如果 dict 有带 "foo" 键的项目则为真</code>
<code class="example">        :if empty(dict)                 " 如果 dict 为空则为真</code>
<code class="example">        :let l = len(dict)              " dict 项目的数量</code>
<code class="example">        :let big = max(dict)            " dict 项目的最大值</code>
<code class="example">        :let small = min(dict)          " dict 项目的最小值</code>
<code class="example">        :let xs = count(dict, 'x')      " 统计 dict 里 'x' 出现的数目</code>
<code class="example">        :let s = string(dict)           " dict 的字符串表示</code>
<code class="example">        :call map(dict, '"&gt;&gt; " .. v:val')  " 在每个项目前加上 "&gt;&gt; "</code>
<code class="example"></code>
<code class="example"></code>
<code class="section">1.5 blob </code>
                                                <b class="vimtag"> <a name="blob">blob</a> </b> <b class="vimtag"> <a name="Blob">Blob</a> </b> <b class="vimtag"> <a name="Blobs">Blobs</a> </b> <b class="vimtag"> <a name="E978">E978</a> </b>
blob 是一个二进制对象。例如，可用来读取文件的映像并通过通道发送。

blob 基本类似于数值的  <a href="eval.html#List">List</a> ，其中每个数值是个 8 位字节的值，从 0 到 255。


<code class="section">blob 建立 </code>

可用  <a href="eval.html#blob-literal">blob-literal</a>  建立 blob: 
<code class="example">        :let b = 0zFF00ED015DAF</code>
字节 (一对十六进制字符) 之间可以插入点号以提高可读性。不改变值本身: 
<code class="example">        :let b = 0zFF00.ED01.5DAF</code>
<code class="example"></code>
用  <a href="builtin.html#readfile()">readfile()</a>  可从文件里读取 blob，其中 <code class="special">{type}</code> 参数设为 "B"。例如: 
<code class="example">        :let b = readfile('image.png', 'B')</code>
<code class="example"></code>
用  <a href="channel.html#ch_readblob()">ch_readblob()</a>  函数可从通道读取 blob。


<code class="section">blob 索引 </code>
                                                        <b class="vimtag"> <a name="blob-index">blob-index</a> </b> <b class="vimtag"> <a name="E979">E979</a> </b>
blob 之后用方括号放上索引可以访问 blob 中的字节。索引从零开始，因而首个字节的
索引为零。 
<code class="example">        :let myblob = 0z00112233</code>
<code class="example">        :let byte = myblob[0]           " 读取首个字节: 0x00</code>
<code class="example">        :let byte = myblob[2]           " 读取第三个字节: 0x22</code>
<code class="example"></code>
负数索引从末尾开始计算。索引 -1 引用 blob 最后一个字节，-2 是倒数第二个字节，
等等。 
<code class="example">        :let last = myblob[-1]          " 读取最后一个字节: 0x33</code>
<code class="example"></code>
用  <a href="builtin.html#get()">get()</a>  函数可以避免索引值非法的错误，如果索引不可用，返回 -1 或你指定的缺
省值: 
<code class="example">        :echo get(myblob, idx)</code>
<code class="example">        :echo get(myblob, idx, 999)</code>
<code class="example"></code>
<code class="example"></code>
<code class="section">blob 遍历 </code>

 <a href="eval.html#:for">:for</a>  循环为 blob 的每个字节执行命令。其中循环变量设为 blob 的每个字节。例如:

<code class="example">        :for byte in 0z112233</code>
<code class="example">        :   call Doit(byte)</code>
<code class="example">        :endfor</code>
会分别用 0x11、0x22 和 0x33 调用 Doit()。


<code class="section">blob 连接 </code>

用 "+" 操作符可以连接两个 blob: 
<code class="example">        :let longblob = myblob + 0z4455</code>
<code class="example">        :let myblob += 0z6677</code>
<code class="example"></code>
要在原位修改 blob，可见下述的  <a href="eval.html#blob-modification">blob-modification</a> 。


<code class="section">blob 部分 </code>

blob 的一部分可用在方括号内指定以冒号分隔的开始处和结束处的索引来获得: 
<code class="example">        :let myblob = 0z00112233</code>
<code class="example">        :let shortblob = myblob[1:2]    " 返回 0z1122</code>
<code class="example">        :let shortblob = myblob[2:-1]   " 返回 0z2233</code>
<code class="example"></code>
开始索引要是省略相当于零。结束索引要是省略相当于 -1。 
<code class="example">        :let endblob = myblob[2:]       " 从项目 2 到尾: 0z2233</code>
<code class="example">        :let shortblob = myblob[2:2]    " 一个字节的 blob: 0z22</code>
<code class="example">        :let otherblob = myblob[:]      " 建立 blob 的备份</code>
<code class="example"></code>
如果开始索引超过 blob 的最后字节，或者结束索引在开始索引之前，返回空 blob。不
报错。

如果结束索引等于或大于列表长度，使用长度减一: 
<code class="example">        :echo myblob[2:8]               " 返回: 0z2233</code>
<code class="example"></code>
<code class="example"></code>
<code class="section">blob 修改 </code>
                                        <b class="vimtag"> <a name="blob-modification">blob-modification</a> </b> <b class="vimtag"> <a name="E1182">E1182</a> </b> <b class="vimtag"> <a name="E1184">E1184</a> </b>
要修改 blob 的特定字节，可以这么用  <a href="eval.html#:let">:let</a> : 
<code class="example">        :let blob[4] = 0x44</code>
<code class="example"></code>
如果索引是 blob 最后索引加一，附加到尾部。再大的索引会报错。

要改变字节序列，可用 [:] 记法: 
<code class="example">        let blob[1:3] = 0z445566</code>
被替换字节序列的长度必须和提供的值相等。 <b class="vimtag"> <a name="E972">E972</a> </b>

要修改 blob 的部分，指定要修改的开始和结束字节。新值必须和范围的字节数相同: 
<code class="example">        :let blob[3:5] = 0z334455</code>
<code class="example"></code>
也可用  <a href="builtin.html#add()">add()</a> 、 <a href="builtin.html#remove()">remove()</a>  和  <a href="builtin.html#insert()">insert()</a>  函数。


<code class="section">blob 同一 </code>

blob 间可以比较是否值相等: 
<code class="example">        if blob == 0z001122</code>
也可以比较是否同一引用: 
<code class="example">        if blob is otherblob</code>
                                                        <b class="vimtag"> <a name="blob-identity">blob-identity</a> </b> <b class="vimtag"> <a name="E977">E977</a> </b>
当 "aa" 变量是 blob 而把它赋值给另一个变量 "bb" 时，两个变量指向同一个 blob。
因而 "is" 操作符返回真值。

用 [:] 或  <a href="builtin.html#copy()">copy()</a>  创建备份时值相等，但是不同的引用: 
<code class="example">        :let blob = 0z112233</code>
<code class="example">        :let blob2 = blob</code>
<code class="example">        :echo blob == blob2</code>
        1 
<code class="example">        :echo blob is blob2</code>
        1 
<code class="example">        :let blob3 = blob[:]</code>
<code class="example">        :echo blob == blob3</code>
        1 
<code class="example">        :echo blob is blob3</code>
        0

blob 建立备份可通过  <a href="builtin.html#copy()">copy()</a>  函数。用 [:] 也可以，已有上述。


<code class="section">1.6 变量的更多细节 </code>
                                                        <b class="vimtag"> <a name="more-variables">more-variables</a> </b>
如果你需要知道变量或表达式的类型，使用  <a href="builtin.html#type()">type()</a>  函数。

如果 <a href="options.html#'viminfo'">'viminfo'</a> 选项包含 '!' 标志位，大写开头且不包含小写字母的全局变量被保存在
viminfo 文件里  <a href="starting.html#viminfo-file">viminfo-file</a> 。

如果 <a href="options.html#'sessionoptions'">'sessionoptions'</a> 选项包含 "global"，大写开头且包含至少一个小写字母的全局
变量被保存在会话文件里  <a href="starting.html#session-file">session-file</a> 。

<code class="section">变量名                  可以保存的位置 </code>
my_var_6                无
My_Var_6                会话文件
MY_VAR_6                viminfo 文件


老式脚本里可以使用花括号来构造变量名，见  <a href="eval.html#curly-braces-names">curly-braces-names</a> 。

</section><hr class="doubleline" /><section class=inner>
<h4>2. 表达式语法                                           <b class="vimtag"> <a name="expression-syntax">expression-syntax</a> </b></h4>                                                        <b class="vimtag"> <a name="E1143">E1143</a> </b>
表达式语法小结，优先级从低到高排列:

 <a href="eval.html#expr1">expr1</a>  expr2
        expr2 ? expr1 : expr1   if-then-else

 <a href="eval.html#expr2">expr2</a>  expr3
        expr3 || expr3 ...      逻辑或

 <a href="eval.html#expr3">expr3</a>  expr4
        expr4 &amp;&amp; expr4 ...      逻辑与

 <a href="eval.html#expr4">expr4</a>  expr5
        expr5 == expr5          等于
        expr5 != expr5          不等于
        expr5 &gt;  expr5          大于
        expr5 &gt;= expr5          大于等于
        expr5 &lt;  expr5          小于
        expr5 &lt;= expr5          小于等于
        expr5 =~ expr5          匹配正则表达式
        expr5 !~ expr5          不匹配正则表达式

        expr5 ==? expr5         等于，忽略大小写
        expr5 ==# expr5         等于，匹配大小写
        等等                    如上，? 忽略大小写，# 则匹配之

        expr5 is expr5          相同的  <a href="eval.html#List">List</a> 、 <a href="eval.html#Dictionary">Dictionary</a>  或  <a href="eval.html#Blob">Blob</a>  实例
        expr5 isnot expr5       不同的  <a href="eval.html#List">List</a> 、 <a href="eval.html#Dictionary">Dictionary</a>  或  <a href="eval.html#Blob">Blob</a>  实例

 <a href="eval.html#expr5">expr5</a>  expr6 &lt;&lt; expr6          按位左移
        expr6 &gt;&gt; expr6          按位右移

 <a href="eval.html#expr6">expr6</a>  expr7
        expr7 +  expr7 ...      数值加法、列表或 blob 连接
        expr7 -  expr7 ...      数值减法
        expr7 .  expr7 ...      字符串连接
        expr7 .. expr7 ...      字符串连接

 <a href="eval.html#expr7">expr7</a>  expr8
        expr8 *  expr8 ...      数值乘法
        expr8 /  expr8 ...      数值除法
        expr8 %  expr8 ...      数值求余

 <a href="eval.html#expr8">expr8</a>  expr9
        <code class="special">&lt;type&gt;</code>expr9             类型检查和转换 (只适用于  <a href="vim9.html#Vim9">Vim9</a> )

 <a href="eval.html#expr9">expr9</a>  expr10
        ! expr9                 逻辑非
        - expr9                 一元减法: 取反
        + expr9                 一元加法: 原值

 <a href="eval.html#expr10">expr10</a>   expr11
        expr10[expr1]           字符串里的字节或者  <a href="eval.html#List">List</a>  的项目
        expr10[expr1 : expr1]   字符串子串或  <a href="eval.html#List">List</a>  的子列表
        expr10.name              <a href="eval.html#Dictionary">Dictionary</a>  的项目
        expr10(expr1, ...)      使用  <a href="eval.html#Funcref">Funcref</a>  变量的函数调用
        expr10-&gt;name(expr1, ...)         <a href="eval.html#method">method</a>  调用

 <a href="eval.html#expr11">expr11</a>   number                数值常数
        "string"                字符串常量，反斜杠有特殊含义
        <code class="badlink">'string'</code>                字符串常量，' 加倍
        [expr1, ...]             <a href="eval.html#List">List</a> 
        {expr1: expr1, ...}      <a href="eval.html#Dictionary">Dictionary</a> 
        #{key: expr1, ...}      老式  <a href="eval.html#Dictionary">Dictionary</a> 
        &amp;option                 选项值
        (expr1)                 嵌套表达式
        variable                内部变量
        va<code class="special">{ria}</code>ble              带花括号的内部变量
        $VAR                    环境变量
        @r                      寄存器 'r' 的值
        function(expr1, ...)    函数调用
        func<code class="special">{ti}</code>on(expr1, ...)  带花括号的函数调用
        {args -&gt; expr1}         老式匿名函数表达式
        (args) =&gt; expr1         Vim9 匿名函数表达式


"..." 标明这一层上的操作可以连接。比如: 
<code class="example">        &amp;nu || &amp;list &amp;&amp; &amp;shell == "csh"</code>
<code class="example"></code>
同一层的表达式从左到右进行分析。

表达式嵌套限于 1000 层深 (用 MSVC 编译时为 300)，以防堆栈溢出和崩溃。 <b class="vimtag"> <a name="E1169">E1169</a> </b>

expr1                           <b class="vimtag"> <a name="expr1">expr1</a> </b> <b class="vimtag"> <a name="ternary">ternary</a> </b> <b class="vimtag"> <a name="falsy-operator">falsy-operator</a> </b> <b class="vimtag"> <a name="??">??</a> </b> <b class="vimtag"> <a name="E109">E109</a> </b>
</section><hr class="singleline" /><section class=inner>

三元操作符: expr2 ? expr1 : expr1
准假值操作符:   expr2 ?? expr1

<code class="section">三元操作符 </code>

老式脚本里 '?' 之前的表达式作为数值求值。如果结果为  <a href="eval.html#TRUE">TRUE</a> ，最终的结果是 '?'
和 ':' 之间的表达式的值，不然最终的结果是 ':' 之后的表达式的值。

 <a href="vim9.html#Vim9">Vim9</a>  脚本里第一个表达式必须作为布尔型求值，见  <a href="vim9.html#vim9-boolean">vim9-boolean</a> 。

例如: 
<code class="example">        :echo lnum == 1 ? "top" : lnum</code>
<code class="example"></code>
因为第一个表达式是 "expr2"，它不能包含另一个 ?:。另外两个表达式则没有这个限
制，从而使得递归使用 ?: 成为可能。例如: 
<code class="example">        :echo lnum == 1 ? "top" : lnum == 1000 ? "last" : lnum</code>
<code class="example"></code>
要使之可读，建议使用续行符  <a href="repeat.html#line-continuation">line-continuation</a> : 
<code class="example">        :echo lnum == 1</code>
<code class="example">        :\      ? "top"</code>
<code class="example">        :\      : lnum == 1000</code>
<code class="example">        :\              ? "last"</code>
<code class="example">        :\              : lnum</code>
<code class="example"></code>
在 ':' 前，你总是应该加上空格，否则它可能被错误用在如 "a:1" 这样的变量里。

<code class="section">准假值操作符 </code>

也有人叫作 "空值合并操作符"，但太复杂了，所以我们就叫它准假值操作符。

先计算 '??' 之前的表达式，如果值为  <a href="eval.html#truthy">truthy</a> ，则把它用作结果。否则，计算 '??'
之后的表达式并用作结果。最常用于为可能为零或空的表达式指定缺省值: 
<code class="example">        echo theList ?? '列表为空'</code>
<code class="example">        echo GetName() ?? '未知'</code>
<code class="example"></code>
以下两者类似，但不完全相同: 
<code class="example">        expr2 ?? expr1</code>
<code class="example">        expr2 ? expr2 : expr1</code>
第二行中的 "expr2" 会计算两次。 <a href="vim9.html#Vim9">Vim9</a>  脚本里 "?" 之前那个 expr2 的类型必须为布
尔型。


expr2 和 expr3                                          <b class="vimtag"> <a name="expr2">expr2</a> </b> <b class="vimtag"> <a name="expr3">expr3</a> </b>
</section><hr class="singleline" /><section class=inner>

expr3 || expr3 ..       逻辑或                  <b class="vimtag"> <a name="expr-barbar">expr-barbar</a> </b>
expr4 &amp;&amp; expr4 ..       逻辑与                  <b class="vimtag"> <a name="expr-&&">expr-&amp;&amp;</a> </b>

"||" 和 "&amp;&amp;" 操作符左右两边各接受一个参数。

老式脚本里参数是 (或转化为) 数值。

 <a href="vim9.html#Vim9">Vim9</a>  脚本里的值必须为布尔型，见  <a href="vim9.html#vim9-boolean">vim9-boolean</a> 。"!!" 可用来把任何类型转换为
布尔型。

运算结果是:

<code class="section">    输入                         输出 </code>
<code class="section">n1      n2              n1 || n2        n1 &amp;&amp; n2 </code>
 <a href="eval.html#FALSE">FALSE</a>   <a href="eval.html#FALSE">FALSE</a>           <a href="eval.html#FALSE">FALSE</a>           <a href="eval.html#FALSE">FALSE</a> 
 <a href="eval.html#FALSE">FALSE</a>   <a href="eval.html#TRUE">TRUE</a>            <a href="eval.html#TRUE">TRUE</a>            <a href="eval.html#FALSE">FALSE</a> 
 <a href="eval.html#TRUE">TRUE</a>    <a href="eval.html#FALSE">FALSE</a>           <a href="eval.html#TRUE">TRUE</a>            <a href="eval.html#FALSE">FALSE</a> 
 <a href="eval.html#TRUE">TRUE</a>    <a href="eval.html#TRUE">TRUE</a>            <a href="eval.html#TRUE">TRUE</a>            <a href="eval.html#TRUE">TRUE</a> 

操作符可以连接。比如: 
<code class="example"></code>
<code class="example">        &amp;nu || &amp;list &amp;&amp; &amp;shell == "csh"</code>
<code class="example"></code>
<code class="note">注意</code> "&amp;&amp;" 比 "||" 优先级高，所以这等价于: 
<code class="example"></code>
<code class="example">        &amp;nu || (&amp;list &amp;&amp; &amp;shell == "csh")</code>
<code class="example"></code>
一旦结果可以确定，表达式使用 "短路" 计算，也就是，不再计算后面的参数，这和 C
的情形类似。比如: 
<code class="example"></code>
<code class="example">        let a = 1</code>
<code class="example">        echo a || b</code>
<code class="example"></code>
这是合法的，即使没有叫 "b" 的变量也是如此。因为 "a" 已经是  <a href="eval.html#TRUE">TRUE</a> ，结果必然是
 <a href="eval.html#TRUE">TRUE</a> 。下面的情形类似: 
<code class="example"></code>
<code class="example">        echo exists("b") &amp;&amp; b == "yes"</code>
<code class="example"></code>
无论 "b" 定义与否，这是合法的。第二个子句只有在 "b" 定义的时候才会被计算。


expr4                                                   <b class="vimtag"> <a name="expr4">expr4</a> </b> <b class="vimtag"> <a name="E1153">E1153</a> </b>
</section><hr class="singleline" /><section class=inner>

expr5 <code class="special">{cmp}</code> expr5

比较两个 expr5 表达式，老式脚本里如果结果为假，返回 0，如果结果为真，返回 1。
 <a href="vim9.html#Vim9">Vim9</a>  脚本里返回值为  <a href="vim9.html#true">true</a>  或  <a href="vim9.html#false">false</a> 。

                        <b class="vimtag"> <a name="expr-%20%20">expr-==</a> </b>  <b class="vimtag"> <a name="expr-!%20">expr-!=</a> </b>  <b class="vimtag"> <a name="expr-%3E">expr-&gt;</a> </b>   <b class="vimtag"> <a name="expr-%3E%20">expr-&gt;=</a> </b>
                        <b class="vimtag"> <a name="expr-%3C">expr-&lt;</a> </b>   <b class="vimtag"> <a name="expr-%3C%20">expr-&lt;=</a> </b>  <b class="vimtag"> <a name="expr-%20%7E">expr-=~</a> </b>  <b class="vimtag"> <a name="expr-!%7E">expr-!~</a> </b>
                        <b class="vimtag"> <a name="expr-%20%20%23">expr-==#</a> </b> <b class="vimtag"> <a name="expr-!%20%23">expr-!=#</a> </b> <b class="vimtag"> <a name="expr-%3E%23">expr-&gt;#</a> </b>  <b class="vimtag"> <a name="expr-%3E%20%23">expr-&gt;=#</a> </b>
                        <b class="vimtag"> <a name="expr-%3C%23">expr-&lt;#</a> </b>  <b class="vimtag"> <a name="expr-%3C%20%23">expr-&lt;=#</a> </b> <b class="vimtag"> <a name="expr-%20%7E%23">expr-=~#</a> </b> <b class="vimtag"> <a name="expr-!%7E%23">expr-!~#</a> </b>
                        <b class="vimtag"> <a name="expr-%20%20?">expr-==?</a> </b> <b class="vimtag"> <a name="expr-!%20?">expr-!=?</a> </b> <b class="vimtag"> <a name="expr-%3E?">expr-&gt;?</a> </b>  <b class="vimtag"> <a name="expr-%3E%20?">expr-&gt;=?</a> </b>
                        <b class="vimtag"> <a name="expr-%3C?">expr-&lt;?</a> </b>  <b class="vimtag"> <a name="expr-%3C%20?">expr-&lt;=?</a> </b> <b class="vimtag"> <a name="expr-%20%7E?">expr-=~?</a> </b> <b class="vimtag"> <a name="expr-!%7E?">expr-!~?</a> </b>
                        <b class="vimtag"> <a name="expr-is">expr-is</a> </b> <b class="vimtag"> <a name="expr-isnot">expr-isnot</a> </b> <b class="vimtag"> <a name="expr-is%23">expr-is#</a> </b> <b class="vimtag"> <a name="expr-isnot%23">expr-isnot#</a> </b>
                        <b class="vimtag"> <a name="expr-is?">expr-is?</a> </b> <b class="vimtag"> <a name="expr-isnot?">expr-isnot?</a> </b> <b class="vimtag"> <a name="E1072">E1072</a> </b>
<code class="section">                使用 <a href="options.html#'ignorecase'">'ignorecase'</a>    匹配大小写     忽略大小写 </code>
等于                    ==              ==#             ==?
不等于                  !=              !=#             !=?
大于                    &gt;               &gt;#              &gt;?
大于等于                &gt;=              &gt;=#             &gt;=?
小于                    &lt;               &lt;#              &lt;?
小于等于                &lt;=              &lt;=#             &lt;=?
匹配正则表达式          =~              =~#             =~?
不匹配正则表达式        !~              !~#             !~?
相同实例                is              is#             is?
不同实例                isnot           isnot#          isnot?

示例:
"abc" ==# "Abc"   结果为 0
"abc" ==? "Abc"   结果为 1
"abc" == "Abc"    如果置位了 <a href="options.html#'ignorecase'">'ignorecase'</a>，结果为 1，不然结果为 0
<code class="note">注意</code>:  <a href="vim9.html#Vim9">Vim9</a>  脚本不使用 <a href="options.html#'ignorecase'">'ignorecase'</a>。

                                                        <b class="vimtag"> <a name="E691">E691</a> </b> <b class="vimtag"> <a name="E692">E692</a> </b>
 <a href="eval.html#List">List</a>  只能和  <a href="eval.html#List">List</a>  比较，而且只能用 "等于"、"不等于"、"is" 和 "isnot"。比较
针对列表的值，递归进行。忽略大小写意味着比较项目的值时忽略大小写。

                                                        <b class="vimtag"> <a name="E735">E735</a> </b> <b class="vimtag"> <a name="E736">E736</a> </b>
 <a href="eval.html#Dictionary">Dictionary</a>  只能和  <a href="eval.html#Dictionary">Dictionary</a>  比较，而且只能用 "等于"、"不等于"、"is" 和
"isnot"。比较针对  <a href="eval.html#Dictionary">Dictionary</a>  的键/值，递归进行。忽略大小写意味着比较项目的值
时忽略大小写。

                                                        <b class="vimtag"> <a name="E694">E694</a> </b>
 <a href="eval.html#Funcref">Funcref</a>  只能和  <a href="eval.html#Funcref">Funcref</a>  比较，而且只能用 "等于"、"不等于"、"is" 和
"isnot"。这里永不忽略大小写。参数或字典是否绑定 (即偏函数的情况) 是有关系的。
绑定的字典必须相等 (或 "is" 的情况下，相同实例)，参数亦然。

要比较函数引用是否指向相同的函数但忽略绑定的字典和参数，用  <a href="builtin.html#get()">get()</a>  来取得函数
名: 
<code class="example">        if get(Part1, 'name') == get(Part2, 'name')</code>
<code class="example">           " Part1 和 Part2 指向相同的函数</code>
<code class="example"></code>
                                                        <b class="vimtag"> <a name="E1037">E1037</a> </b>
 <a href="eval.html#List">List</a> 、 <a href="eval.html#Dictionary">Dictionary</a>  或  <a href="eval.html#Blob">Blob</a>  用 "is" 或 "isnot" 时，检查表达式是否指向同一个
 <a href="eval.html#List">List</a>  、 <a href="eval.html#Dictionary">Dictionary</a>  或  <a href="eval.html#Blob">Blob</a>  实例。一个  <a href="eval.html#List">List</a>  的备份和原来的  <a href="eval.html#List">List</a>  不同。
如果不是  <a href="eval.html#List">List</a> 、 <a href="eval.html#Dictionary">Dictionary</a>  或  <a href="eval.html#Blob">Blob</a> ，用 "is" 等价于用 "等于"，而 "isnot"
等价于 "不等于"，有一点区别: 不同的类型总认为有不同的值: 
<code class="example">        echo 4 == '4'</code>
<code class="example">        1</code>
<code class="example">        echo 4 is '4'</code>
<code class="example">        0</code>
<code class="example">        echo 0 is []</code>
<code class="example">        0</code>
"is#"/"isnot#" 和 "is?"/"isnot?" 用于强制匹配和忽略大小写。
 <a href="vim9.html#Vim9">Vim9</a>  脚本里，此处不适用，两个字符串永不等价。

老式脚本里，如果比较字符串和数值，字符串被转化成数值，而比较是在数值之间进行
的。这意味着: 
<code class="example">        echo 0 == 'x'</code>
<code class="example">        1</code>
因为 'x' 转化的数值为零。不过: 
<code class="example">        echo [0] == ['x']</code>
<code class="example">        0</code>
在列表或字典里不进行这种转换。

 <a href="vim9.html#Vim9">Vim9</a>  脚本里类型必须匹配。

如果比较两个字符串，使用 strcmp() 或 stricmp()。因而，比较的是数学上的差异 (比
较字节码)，而不必然是本地语言的字母的差异。

如果操作符后带上 '#'，或者 <a href="options.html#'ignorecase'">'ignorecase'</a> 关闭时使用无 '#' 的版本时，比较使用
strcmp(): 大小写相关。

如果操作符后带上 '?'，或者 <a href="options.html#'ignorecase'">'ignorecase'</a> 打开时使用无 '?' 的版本时，比较使用
stricmp(): 大小写无关。

这里 <a href="options.html#'smartcase'">'smartcase'</a> 不适用。

"=~" 和 "!~" 操作符使用右边的参数作为模式来匹配左边的参数。模式的定义见
 <a href="pattern.html#pattern">pattern</a> 。匹配进行时，总是假设置位了 <a href="options.html#'magic'">'magic'</a> 并且 <a href="options.html#'cpoptions'">'cpoptions'</a> 为空，无论
<a href="options.html#'magic'">'magic'</a> 或 <a href="options.html#'cpoptions'">'cpoptions'</a> 实际的值为何。这使得脚本可移植。要避免在正则表达式里使
用的反斜杠需要加倍的问题，可以使用单引号的字符串，见  <a href="eval.html#literal-string">literal-string</a> 。
既然字符串假定为单行，多行的模式 (包含 \n，即反斜杠-n) 不会被匹配。不过，按本
义出现的单个 NL 字符可以像普通字符一样匹配。比如:
        "foo\nbar" =~ "\n"      结果为 1
        "foo\nbar" =~ "\\n"     结果为 0


expr5                                           <b class="vimtag"> <a name="expr5">expr5</a> </b> <b class="vimtag"> <a name="bitwise-shift">bitwise-shift</a> </b>
</section><hr class="singleline" /><section class=inner>
expr6 &lt;&lt; expr6  按位左移                                        <b class="vimtag"> <a name="expr-%3C%3C">expr-&lt;&lt;</a> </b>
expr6 &gt;&gt; expr6  按位右移                                        <b class="vimtag"> <a name="expr-%3E%3E">expr-&gt;&gt;</a> </b>
                                                        <b class="vimtag"> <a name="E1282">E1282</a> </b> <b class="vimtag"> <a name="E1283">E1283</a> </b>
"&lt;&lt;" 和 "&gt;&gt;" 操作符可用于用左侧操作数按位左移或右移右侧操作数指定的位数。两个
操作数都用作正数。用 "&gt;&gt;" 按位右移时最高位 (有时称为符号位) 被清零。如果右侧操
作数 (位移量) 大于数值最大位数 ( <a href="eval.html#v:numbersize">v:numbersize</a> )，返回零。


expr6 和 expr7                          <b class="vimtag"> <a name="expr6">expr6</a> </b> <b class="vimtag"> <a name="expr7">expr7</a> </b> <b class="vimtag"> <a name="E1036">E1036</a> </b> <b class="vimtag"> <a name="E1051">E1051</a> </b>
</section><hr class="singleline" /><section class=inner>
expr7 +  expr7  数值加法、 <a href="eval.html#List">List</a>  或  <a href="eval.html#Blob">Blob</a>  连接                 <b class="vimtag"> <a name="expr-+">expr-+</a> </b>
expr7 -  expr7  数值减法                                        <b class="vimtag"> <a name="expr--">expr--</a> </b>
expr7 .  expr7  字符串连接                                      <b class="vimtag"> <a name="expr-.">expr-.</a> </b>
expr7 .. expr7  字符串连接                                      <b class="vimtag"> <a name="expr-..">expr-..</a> </b>

 <a href="eval.html#Lists">Lists</a>  只能用 "+"，而且两个 expr7 必须都是列表。返回两者连接以后的新列表。

字符串连接建议使用 ".."，因为 "." 有二义性，也用于  <a href="eval.html#Dict">Dict</a>  的成员访问和浮点数。
 <a href="vim9.html#Vim9">Vim9</a>  脚本里和当  <a href="eval.html#vimscript-version">vimscript-version</a>  为 2 或更高时，不允许使用 "."。

 <a href="vim9.html#Vim9">Vim9</a>  脚本里 ".." 的参数如果为简单类型，即数值、浮点、特殊和布尔型时，转换为
字符串。其他类型必须使用  <a href="builtin.html#string()">string()</a> 。

expr8 *  expr8 数值乘法                                         <b class="vimtag"> <a name="expr-star">expr-star</a> </b>
expr8 /  expr8 数值除法                                         <b class="vimtag"> <a name="expr-%2F">expr-/</a> </b>
expr8 %  expr8 数值求余                                         <b class="vimtag"> <a name="expr-%">expr-%</a> </b>

老式脚本里除了 "." 和 ".." 以外，这里所有的操作都把字符串转化成数值。
按位操作运算见  <a href="builtin.html#and()">and()</a> 、 <a href="builtin.html#or()">or()</a>  和  <a href="builtin.html#xor()">xor()</a> 。

<code class="note">注意</code> 老式脚本里 "+" 和 ".." 的差异:
        "123" + "456" = 579
        "123" .. "456" = "123456"

因为 '..' 和 '+' 与 '-' 的优先级相同，你需要把: 
<code class="example">        1 .. 90 + 90.0</code>
看作: 
<code class="example">        (1 .. 90) + 90.0</code>
老式脚本里这没问题，因为字符串 "190" 被自动转换为数值 190，然后和浮点数 90.0
相加。不过: 
<code class="example">        1 .. 90 * 90.0</code>
应被看作: 
<code class="example">        1 .. (90 * 90.0)</code>
因为 '..' 的优先级比 '*' 低，这 <code class="emphasis">不能</code> 工作，因为它试图连接浮点数和字符串。

数值除以零时，结果取决于该值:
          0 / 0  = -0x80000000  (类似于浮点数的 NaN)
         &gt;0 / 0  =  0x7fffffff  (类似于正无穷大)
         &lt;0 / 0  = -0x7fffffff  (类似于负无穷大)
        (Vim 7.2 之前，总是返回 0x7fffffff)
 <a href="vim9.html#Vim9">Vim9</a>  脚本里数值除以零是错误。 <b class="vimtag"> <a name="E1154">E1154</a> </b>

启用 64-位数值支持时:
          0 / 0  = -0x8000000000000000  (类似于浮点数的 NaN)
         &gt;0 / 0  =  0x7fffffffffffffff  (类似于正无穷大)
         &lt;0 / 0  = -0x7fffffffffffffff  (类似于负无穷大)

如果 '%' 的右边为零，结果为 0。

这些操作不适用于  <a href="eval.html#Funcref">Funcref</a> 。

而 "."、".." 和 "%" 也不适用于浮点数。 <b class="vimtag"> <a name="E804">E804</a> </b> <b class="vimtag"> <a name="E1035">E1035</a> </b>


expr8                                                   <b class="vimtag"> <a name="expr8">expr8</a> </b>
</section><hr class="singleline" /><section class=inner>
<code class="special">&lt;type&gt;</code>expr9

只用于  <a href="vim9.html#Vim9">Vim9</a>  脚本，见  <a href="vim9.html#type-casting">type-casting</a> 。


expr9                                                   <b class="vimtag"> <a name="expr9">expr9</a> </b>
</section><hr class="singleline" /><section class=inner>
! expr9                 逻辑非                  <b class="vimtag"> <a name="expr-!">expr-!</a> </b>
- expr9                 一元减法: 取反          <b class="vimtag"> <a name="expr-unary--">expr-unary--</a> </b>
+ expr9                 一元加法: 原值          <b class="vimtag"> <a name="expr-unary-+">expr-unary-+</a> </b>

'!' 把  <a href="eval.html#TRUE">TRUE</a>  变为  <a href="eval.html#FALSE">FALSE</a> ， <a href="eval.html#FALSE">FALSE</a>  变为  <a href="eval.html#TRUE">TRUE</a>  (一)。
'-' 改变数值的符号。
'+' 保持原值。<code class="note">注意</code> "++" 没有效果 (<code class="vim">译者注</code>: 即，不是增量操作符)。

老式脚本里字符串会先转化为数值。<code class="note">注意</code> 如果字符串不以数位开始，结果可能会出乎意
料。

 <a href="vim9.html#Vim9">Vim9</a>  脚本里 "-" 和 "+" 用于非数值的类型时会报错。

 <a href="vim9.html#Vim9">Vim9</a>  脚本里 "!" 可用于任何类型，结果总是布尔型。用 "!!" 可按照其值是否
 <a href="eval.html#falsy">falsy</a>  来把任何类型转换为布尔型。

可以重复和混合这三种运算。例如:
        !-1         == 0
        !!8         == 1
        --9         == 9


expr10                                                  <b class="vimtag"> <a name="expr10">expr10</a> </b>
</section><hr class="singleline" /><section class=inner>
此处表达式或是  <a href="eval.html#expr11">expr11</a> ，或是任意顺序的下面各项之一的序列。例如这些都可以:
        expr10[expr1].name
        expr10.name[expr1]
        expr10(expr1, ...)[expr1].name
        expr10-&gt;(expr1, ...)[expr1]
计算总是从左到右。

expr10[expr1]           字符串或  <a href="eval.html#List">List</a>  的项目          <b class="vimtag"> <a name="expr-[]">expr-[]</a> </b> <b class="vimtag"> <a name="E111">E111</a> </b>
                                                <b class="vimtag"> <a name="E909">E909</a> </b> <b class="vimtag"> <a name="subscript">subscript</a> </b> <b class="vimtag"> <a name="E1062">E1062</a> </b>
老式 Vim 脚本里:
如果 expr10 是数值或字符串，结果是字符串，包含 expr10 里第 expr1 个字节。
expr10 视作字符串 (数值自动转换为字符串)，expr1 视作数值。这里不识别多字节编
码，但可考虑使用  <a href="builtin.html#byteidx()">byteidx()</a> ，或用  <a href="builtin.html#split()">split()</a>  把字符串变为字符的列表。例如，要
得到光标所在的字节: 
<code class="example">        :let c = getline(line("."))[col(".") - 1]</code>
<code class="example"></code>
 <a href="vim9.html#Vim9">Vim9</a>  脚本里:                                          <b class="vimtag"> <a name="E1147">E1147</a> </b> <b class="vimtag"> <a name="E1148">E1148</a> </b>
如果 expr10 是字符串，结果是字符串，包含 expr10 里第 expr1 个单个字符 (包含任
何的组合字符)。要用字节索引，使用  <a href="builtin.html#strpart()">strpart()</a> 。

索引 0 给出第一个字节。要小心: 文本列号可是从 1 开始的！

如果字符串的长度小于索引值，结果为空字符串。负索引总是给出空字符串 (原因: 反向
兼容)。用 [-1:] 得到最后一个字节或字符。
Vim9 脚本中，负索引的用法同列表中的相同: 由结尾开始反向计算。

如果 expr10 是  <a href="eval.html#List">List</a> ，返回索引值为 expr1 的项目。可用的索引值见
 <a href="eval.html#list-index">list-index</a> 。如果索引越界，产生错误。例如: 
<code class="example">        :let item = mylist[-1]          " 得到最后一个项目</code>
<code class="example"></code>
一般的，如果  <a href="eval.html#List">List</a>  索引大于等于  <a href="eval.html#List">List</a>  的长度，或者比  <a href="eval.html#List">List</a>  的长度更负，产生
错误。


expr10[expr1a : expr1b] 子字符串或  <a href="eval.html#sublist">sublist</a>             <b class="vimtag"> <a name="expr-[:]">expr-[:]</a> </b> <b class="vimtag"> <a name="substring">substring</a> </b>

如果 expr10 是字符串，结果是子字符串，包含第 expr1a 到第 expr1b (包含) 个字节
或字符。expr10 视作字符串，expr1a 和 expr1b 视作数值。

在老式 Vim 脚本里，索引是字节索引。这里不识别多字节编码，需用  <a href="builtin.html#byteidx()">byteidx()</a>  来计
算索引值。如果 expr10 为数值，先转换为字符串。

在 Vim9 脚本里索引为字符索引，包含组合字符。要使用字节索引，可用  <a href="builtin.html#strpart()">strpart()</a> 。
要用字符索引但不带组合字符，可用  <a href="builtin.html#strcharpart()">strcharpart()</a> 。

索引 expr1b 包含在内，亦即是闭的。要用开的索引值，可用  <a href="builtin.html#slice()">slice()</a>  函数。

如果省略 expr1a，用零。如果省略 expr1b，用字符串的长度减一。

可以用负数来从字符串尾部开始计算位置。-1 代表最后一个字符，-2 倒数第二个，依此
类推。

如果索引越界，忽略这些字符。如果 expr1b 小于 expr1a，结果是空字符串。

例如: 
<code class="example">        :let c = name[-1:]              " 字符串最后一个字节</code>
<code class="example">        :let c = name[0:-1]             " 整个字符串</code>
<code class="example">        :let c = name[-2:-2]            " 字符串倒数第二个字节</code>
<code class="example">        :let s = line(".")[4:]          " 从第五个字节到最后</code>
<code class="example">        :let s = s[:-3]                 " 删除最后两个字节</code>

                                                        <b class="vimtag"> <a name="slice">slice</a> </b>
如果 expr10 是  <a href="eval.html#List">List</a> ，结果是新的  <a href="eval.html#List">List</a> ，包含 expr1 和 expr1b 索引指定的项
目。和上面描述的字符串情形类似。另见下面的  <a href="eval.html#sublist">sublist</a> 。例如: 
<code class="example">        :let l = mylist[:3]             " 前四个项目</code>
<code class="example">        :let l = mylist[4:4]            " 单个项目的列表</code>
<code class="example">        :let l = mylist[:]              " 列表的浅备份</code>
<code class="example"></code>
如果 expr10 是  <a href="eval.html#Blob">Blob</a> ，结果是新的  <a href="eval.html#Blob">Blob</a> ，包含从索引 expr1a 到 expr1b 的字节，
闭区间。例如: 
<code class="example">        :let b = 0zDEADBEEF</code>
<code class="example">        :let bs = b[1:2]                " 0zADBE</code>
<code class="example">        :let bs = b[:]                  " 0zDEADBEEF 的备份</code>
<code class="example"></code>
在  <a href="eval.html#Funcref">Funcref</a>  上用 expr10[expr1] 或 expr10[expr1a : expr1b] 出错。

小心命名空间和变量后加冒号的子列表用法引起的混淆: 
<code class="example">        mylist[n:]     " 使用变量 n</code>
<code class="example">        mylist[s:]     " 使用命名空间 s:，报错！</code>
<code class="example"></code>
<code class="example"></code>
expr10.name              <a href="eval.html#Dictionary">Dictionary</a>  的项目             <b class="vimtag"> <a name="expr-entry">expr-entry</a> </b>
                                                        <b class="vimtag"> <a name="E1203">E1203</a> </b> <b class="vimtag"> <a name="E1229">E1229</a> </b>
如果 expr10 是一个  <a href="eval.html#Dictionary">Dictionary</a>  且后跟句号再跟一个名字，该名字用作
 <a href="eval.html#Dictionary">Dictionary</a>  的键。这相当于: expr10[name]。

该名字必须由字母数字字符组成。这和变量名一样，不过这里可以用数字开始。但不能用
花括号。

句号前后不能用空白。

例如: 
<code class="example">        :let dict = {"one": 1, 2: "two"}</code>
<code class="example">        :echo dict.one          " 显示 "1"</code>
<code class="example">        :echo dict.2            " 显示 "two"</code>
<code class="example">        :echo dict .2           " 因为点号前有空格，报错</code>
<code class="example"></code>
<code class="note">注意</code> 句号也用于字符串连接。要避免混淆，用于字符串连接的句号前后加上空白。


expr10(expr1, ...)       <a href="eval.html#Funcref">Funcref</a>  函数调用              <b class="vimtag"> <a name="E1085">E1085</a> </b>

如果 expr10 是  <a href="eval.html#Funcref">Funcref</a>  类型的变量，调用它指向的函数。


expr10-&gt;name([args])    方法调用                        <b class="vimtag"> <a name="method">method</a> </b> <b class="vimtag"> <a name="-%3E">-&gt;</a> </b>
expr10-&gt;<code class="special">{lambda}</code>([args])
                                                        <b class="vimtag"> <a name="E260">E260</a> </b> <b class="vimtag"> <a name="E276">E276</a> </b> <b class="vimtag"> <a name="E1265">E1265</a> </b>
对同时作为全局函数存在的方法而言，这等价于: 
<code class="example">        name(expr10 [, args])</code>
也有专用于 "expr10" 类型的方法。

可用于链式调用，把一个方法的结果传给下一个方法: 
<code class="example">        mylist-&gt;filter(filterexpr)-&gt;map(mapexpr)-&gt;sort()-&gt;join()</code>

使用匿名函数的示例: 
<code class="example">        GetPercentage()-&gt;{x -&gt; x * 100}()-&gt;printf('%d%%')</code>

使用 -&gt; 时，先应用  <a href="eval.html#expr9">expr9</a>  操作符，所以: 
<code class="example">        -1.234-&gt;string()</code>
等价于: 
<code class="example">        (-1.234)-&gt;string()</code>
而 <code class="emphasis">不是</code> : 
<code class="example">        -(1.234-&gt;string())</code>

"-&gt;" 之后的部分可以是名字、简单表达式 (不含括号)、或括号内的任何表达式: 
<code class="example">        base-&gt;name(args)</code>
<code class="example">        base-&gt;some.name(args)</code>
<code class="example">        base-&gt;alist[idx](args)</code>
<code class="example">        base-&gt;(getFuncRef())(args)</code>
<code class="note">注意</code> 最后一个调用中，base 传递给 "(getFuncRef())" 返回的函数，插入在 "args" 之
前。 <b class="vimtag"> <a name="E1275">E1275</a> </b>

                                                        <b class="vimtag"> <a name="E274">E274</a> </b>
"-&gt;name(" 内部不能包含空白。"-&gt;" 之前和 "(" 之后可有空白，所以可以这样断行: 
<code class="example">        mylist</code>
<code class="example">        \ -&gt;filter(filterexpr)</code>
<code class="example">        \ -&gt;map(mapexpr)</code>
<code class="example">        \ -&gt;sort()</code>
<code class="example">        \ -&gt;join()</code>
<code class="example"></code>
使用匿名函数形式时，} 和 ( 之间不能有空白。


                                                        <b class="vimtag"> <a name="expr11">expr11</a> </b>
number
</section><hr class="singleline" /><section class=inner>
number                  数值常数                        <b class="vimtag"> <a name="expr-number">expr-number</a> </b>
                        <b class="vimtag"> <a name="0x">0x</a> </b> <b class="vimtag"> <a name="hex-number">hex-number</a> </b> <b class="vimtag"> <a name="0o">0o</a> </b> <b class="vimtag"> <a name="octal-number">octal-number</a> </b> <b class="vimtag"> <a name="binary-number">binary-number</a> </b>

十进制、十六进制 (0x 或 0X 开始)、二进制 (0b 或 0B 开始) 和 八进制 (0、0o 或
0O 开始)。

假定使用 64 位数值 (见  <a href="eval.html#v:numbersize">v:numbersize</a> )，无符号数值被截短为
0x7fffffffffffffff 或 9223372036854775807。用 -1 可得到 0xffffffffffffffff。

                                                <b class="vimtag"> <a name="floating-point-format">floating-point-format</a> </b>
浮点数可用两种形式给出:

        [-+]<code class="special">{N}</code>.<code class="special">{M}</code>
        [-+]<code class="special">{N}</code>.<code class="special">{M}</code>[eE][-+]<code class="special">{exp}</code>

<code class="special">{N}</code> 和 <code class="special">{M}</code> 都是数值。<code class="special">{N}</code> 和 <code class="special">{M}</code> 都必须存在，且只能包含数位，例外是  <a href="vim9.html#Vim9">Vim9</a>  脚本
里 <code class="special">{N}</code> 里的数位之间可有单引号，会被忽略。
[-+] 意味着有一个可选的正负号。
<code class="special">{exp}</code> 是指数部分，以 10 为基。
只能接受小数点，逗号不行。这和当前的 locale 无关。

示例:
        123.456
        +0.0001
        55.0
        -0.123
        1.234e03
        1.0E-6
        -3.1416e+88

下面的形式是 <code class="emphasis">非法的</code> :
        3.              <code class="special">{M}</code> 为空
        1e40            <code class="special">{M}</code> 为空

理据:
浮点数引入之前，文本 "123.456" 被解释为两个数值 "123" 和 "456"，转换为字符串，
然后进行连接而生成字符串 "123456"。这被认为没有意义，也没有找到有意使用此特性
的 Vim 脚本，因此我们采纳了这种普遍的浮点数记法，而接受其后向不兼容性。

                                                        <b class="vimtag"> <a name="float-pi">float-pi</a> </b> <b class="vimtag"> <a name="float-e">float-e</a> </b>
可以复制-粘贴的一些常用值: 
<code class="example">        :let pi = 3.14159265359</code>
<code class="example">        :let e  = 2.71828182846</code>
或者，如果不要直接写浮点常量，可用相应的函数，就像这样: 
<code class="example">        :let pi = acos(-1.0)</code>
<code class="example">        :let e  = exp(1.0)</code>

                                                <b class="vimtag"> <a name="floating-point-precision">floating-point-precision</a> </b>
浮点数的精度和取值范围取决于 Vim 编译时使用的库如何理解 "double"。运行时无法改
变。

浮点数  <a href="eval.html#Float">Float</a>  的显示缺省使用 6 位十进制位，类似于 printf("%g", f)。使用
 <a href="builtin.html#printf()">printf()</a>  函数时可以指定其它位数。例如: 
<code class="example">        :echo printf('%.15e', atan(1))</code>
        7.853981633974483e-01



string                                  <b class="vimtag"> <a name="string">string</a> </b> <b class="vimtag"> <a name="String">String</a> </b> <b class="vimtag"> <a name="expr-string">expr-string</a> </b> <b class="vimtag"> <a name="E114">E114</a> </b>
</section><hr class="singleline" /><section class=inner>
"string"                字符串常量              <b class="vimtag"> <a name="expr-quote">expr-quote</a> </b>

<code class="note">注意</code> 使用的是双引号。

字符串常量接受以下特殊字符:
\...    三位八进制数 (例如，"\316")
\..     两位八进制数 (必须后跟非数字)
\.      一位八进制数 (必须后跟非数字)
\x..    两位十六进制数指定的字节 (例如，"\x1f")
\x.     一位十六进制数指定的字节 (必须后跟非十六进制数字)
\X..    同 \x..
\X.     同 \x.
\u....  四位十六进制指定的字符。根据 <a href="options.html#'encoding'">'encoding'</a> 的当前值决定的编码进行存贮 (例
        如，"\u02a4")
\U....  同 \u 但接受多达 8 位十六进制数。
\b      退格 <code class="special">&lt;BS&gt;</code>
\e      escape <code class="special">&lt;Esc&gt;</code>
\f      换页 0x0C
\n      换行 <code class="special">&lt;NL&gt;</code>
\r      回车 <code class="special">&lt;CR&gt;</code>
\t      制表 <code class="special">&lt;Tab&gt;</code>
\\      反斜杠
\"      双引号
\<code class="special">&lt;xxx&gt;</code>  "xxx" 命名的特殊字符，例如 "\<code class="special">&lt;C-W&gt;</code>" 代表 <code class="keystroke">CTRL-W</code>。用于映射，0x80 字节被
        转义。
        双引号必须转义: "&lt;M-\"&gt;"。
        不要用 <code class="special">&lt;Char-xxxx&gt;</code> 来得到 UTF-8 字符，用上面提到的 \uxxxxx。
\&lt;*xxx&gt; 类似于 \<code class="special">&lt;xxx&gt;</code>，但在之前附加修饰符而不是把它包含到字符里。例如，
        "\<code class="special">&lt;C-w&gt;</code>" 是单个字符 0x17，而 "\&lt;*C-w&gt;" 是四个字节: CTRL 修饰符对应 3
        个，然后是字符 "W"。

<code class="note">注意</code> "\xff" 保存为字节 255，在某些编码中它是不合法的。使用 "\u00ff" 可以按照
<a href="options.html#'encoding'">'encoding'</a> 的当前值保存字符 255。

<code class="note">注意</code> "\000" 和 "\x00" 强制字符串结束。


blob-literal                            <b class="vimtag"> <a name="blob-literal">blob-literal</a> </b> <b class="vimtag"> <a name="E973">E973</a> </b>
</section><hr class="singleline" /><section class=inner>

0z 或 0Z 开头的十六进制序列，字符数目不限。序列必须是偶数位的十六进制字符。例
如: 
<code class="example">        :let b = 0zFF00ED015DAF</code>
<code class="example"></code>
<code class="example"></code>
literal-string                                          <b class="vimtag"> <a name="literal-string">literal-string</a> </b> <b class="vimtag"> <a name="E115">E115</a> </b>
</section><hr class="singleline" /><section class=inner>
<code class="badlink">'string'</code>                字符串常量                      <b class="vimtag"> <a name="expr-'">expr-'</a> </b>

<code class="note">注意</code> 使用的是单引号。

字符串这里按原义出现。不去掉反斜杠，它也没有特殊含义。唯一的特例是两个单引号代
表一个单引号。

单引号字符串有助于模式的使用，因为反斜杠不再需要加倍。以下两个命令等价: 
<code class="example">        if a =~ "\\s*"</code>
<code class="example">        if a =~ '\s*'</code>
<code class="example"></code>
<code class="example"></code>
interpolated-string                             <b class="vimtag"> <a name="$quote">$quote</a> </b> <b class="vimtag"> <a name="interpolated-string">interpolated-string</a> </b>
</section><hr class="singleline" /><section class=inner>
$"string"               插值字符串常量                          <b class="vimtag"> <a name="expr-$quote">expr-$quote</a> </b>
$<code class="badlink">'string'</code>               插值按本义字符串常量                    <b class="vimtag"> <a name="expr-$'">expr-$'</a> </b>

插值字符串是  <a href="eval.html#string">string</a>  和  <a href="eval.html#literal-string">literal-string</a>  的扩展，可插入 Vim 脚本表达式的值
(见  <a href="eval.html#expr1">expr1</a> )。任何返回一个值的表达式必须用花括号包围。该值被转换为字符串。所有
文本和表达式的返回值被连接为一个新字符串。
                                                        <b class="vimtag"> <a name="E1278">E1278</a> </b> <b class="vimtag"> <a name="E1279">E1279</a> </b>
在字符串内容里要包含开花括号 '{' 或闭花括号 '}'，给它们加倍。双引号字符串也可
用反斜杠。单独的闭花括号 '}' 会报错。

示例: 
<code class="example">        let your_name = input("请问尊姓大名? ")</code>
<code class="section">        请问尊姓大名?  Peter </code>

<code class="example">        echo</code>
<code class="example">        echo $"你好, {your_name}!"</code>
<code class="section">        你好, Peter! </code>

<code class="example">        echo $"{{9}} 的开方根是 {sqrt(9)}"</code>
<code class="section">        <code class="special">{9}</code> 的平方根是 3.0 </code>


option                                          <b class="vimtag"> <a name="expr-option">expr-option</a> </b> <b class="vimtag"> <a name="E112">E112</a> </b> <b class="vimtag"> <a name="E113">E113</a> </b>
</section><hr class="singleline" /><section class=inner>
&amp;option                 选项值，如有存在，使用局部值
&amp;g:option               全局选项值
&amp;l:option               局部选项值

例如: 
<code class="example">        echo "tabstop is " .. &amp;tabstop</code>
<code class="example">        if &amp;insertmode</code>
<code class="example"></code>
这里可以使用任何选项值。见  <a href="options.html#options">options</a> 。如果指定要使用局部值，但不存在局部于缓冲
区或局部于窗口的选项，则还是使用全局值。


register                                                <b class="vimtag"> <a name="expr-register">expr-register</a> </b> <b class="vimtag"> <a name="@r">@r</a> </b>
</section><hr class="singleline" /><section class=inner>
@r                      寄存器 'r' 的值

结果是命名寄存器的内容，以单个字符串表达。换行符在需要时会被插入。要得到无名寄
存器的内容，使用 @" 或 @@。可用寄存器的相关解释可见  <a href="change.html#registers">registers</a> 。

如果用 '=' 寄存器，你得到表达式自身，而不是它计算的结果。用  <a href="builtin.html#eval()">eval()</a>  来进行计
算。


nesting                                         <b class="vimtag"> <a name="expr-nesting">expr-nesting</a> </b> <b class="vimtag"> <a name="E110">E110</a> </b>
</section><hr class="singleline" /><section class=inner>
(expr1)                 嵌套表达式


environment variable                                    <b class="vimtag"> <a name="expr-env">expr-env</a> </b>
</section><hr class="singleline" /><section class=inner>
$VAR                    环境变量

任何环境变量的字符串值。如果该环境变量没有定义，结果为空字符串。

也可用  <a href="builtin.html#getenv()">getenv()</a>  和  <a href="builtin.html#setenv()">setenv()</a>  函数，它们支持非字母数字的环境变量名。
可用  <a href="builtin.html#environ()">environ()</a>  函数得到包含所有环境变量的字典。


                                                <b class="vimtag"> <a name="expr-env-expand">expr-env-expand</a> </b>
<code class="note">注意</code> 直接使用 $VAR 和使用 expand("$VAR") 有区别。直接使用的形式只能扩展当前
Vim 会话所知的环境变量。使用 expand() 会先尝试当前 Vim 会话所知的环境变量，如
果不成功，则使用外壳扩展该变量。这会变慢，但可以用来扩展只有外壳知道的变量。
例如: 
<code class="example">        :echo $shell</code>
<code class="example">        :echo expand("$shell")</code>
前者可能不会回显任何内容，后者会回显 $shell 变量 (如果你的外壳支持的话)。


internal variable                       <b class="vimtag"> <a name="expr-variable">expr-variable</a> </b> <b class="vimtag"> <a name="E1015">E1015</a> </b> <b class="vimtag"> <a name="E1089">E1089</a> </b>
</section><hr class="singleline" /><section class=inner>
variable                内部变量
见下面的  <a href="eval.html#internal-variables">internal-variables</a> 。


function call           <b class="vimtag"> <a name="expr-function">expr-function</a> </b> <b class="vimtag"> <a name="E116">E116</a> </b> <b class="vimtag"> <a name="E118">E118</a> </b> <b class="vimtag"> <a name="E119">E119</a> </b> <b class="vimtag"> <a name="E120">E120</a> </b>
</section><hr class="singleline" /><section class=inner>
function(expr1, ...)    函数调用
见下面的  <a href="eval.html#functions">functions</a> 。


lambda expression                               <b class="vimtag"> <a name="expr-lambda">expr-lambda</a> </b> <b class="vimtag"> <a name="lambda">lambda</a> </b>
</section><hr class="singleline" /><section class=inner>
{args -&gt; expr1}         老式匿名函数表达式                      <b class="vimtag"> <a name="E451">E451</a> </b>
(args) =&gt; expr1          <a href="vim9.html#Vim9">Vim9</a>  匿名函数表达式

匿名函数表达式创建一个新的无名函数，返回  <a href="eval.html#expr1">expr1</a>  的计算结果。匿名函数表达式和
 <a href="eval.html#user-functions">user-functions</a>  的区别如下:

1. 匿名函数表达式的本体是  <a href="eval.html#expr1">expr1</a>  而不是  <a href="intro.html#Ex">Ex</a>  命令序列。
2. 前缀 "a:" 不用于参数。例如: 
<code class="example">        :let F = {arg1, arg2 -&gt; arg1 - arg2}</code>
<code class="example">        :echo F(5, 2)</code>
        3

参数可选。例如: 
<code class="example">        :let F = {-&gt; 'error function'}</code>
<code class="example">        :echo F('ignored')</code>
        error function

 <a href="vim9.html#Vim9">Vim9</a>  脚本中不只使用另一种语法，而且进行类型检查，且可分割为多行，见
 <a href="vim9.html#vim9-lambda">vim9-lambda</a> 。

                                                        <b class="vimtag"> <a name="closure">closure</a> </b>
匿名函数表达式可能访问外层变量和参数。这通常被称为闭包。下例中匿名函数可以使用
已存在于函数作用域的 "i" 和 "a:arg"。在函数返回后它们依然有效: 
<code class="example">        :function Foo(arg)</code>
<code class="example">        :  let i = 3</code>
<code class="example">        :  return {x -&gt; x + i - a:arg}</code>
<code class="example">        :endfunction</code>
<code class="example">        :let Bar = Foo(4)</code>
<code class="example">        :echo Bar(6)</code>
        5

<code class="note">注意</code> 变量必须在 lambda 定义之前已存在于外部作用域。另见  <a href="userfunc.html#:func-closure">:func-closure</a> 。

可以这样来检查匿名函数和闭包的支持: 
<code class="example">        if has('lambda')</code>
<code class="example"></code>
示例如何在  <a href="builtin.html#sort()">sort()</a> 、 <a href="builtin.html#map()">map()</a>  和  <a href="builtin.html#filter()">filter()</a>  中使用匿名函数: 
<code class="example">        :echo map([1, 2, 3], {idx, val -&gt; val + 1})</code>
        [2, 3, 4] 
<code class="example">        :echo sort([3,7,2,1,4], {a, b -&gt; a - b})</code>
        [1, 2, 3, 4, 7]

匿名函数表达式也可用于通道、作业和定时器中: 
<code class="example">        :let timer = timer_start(500,</code>
<code class="example">                        \ {-&gt; execute("echo 'Handler called'", "")},</code>
<code class="example">                        \ {'repeat': 3})</code>
        Handler called
        Handler called
        Handler called

<code class="note">注意</code> 如果闭包在它依赖的上下文里被引用，可能会导致内存使用不能被释放: 
<code class="example">        function Function()</code>
<code class="example">           let x = 0</code>
<code class="example">           let F = {-&gt; x}</code>
<code class="example">         endfunction</code>
此闭包在函数作用域使用 "x"，而相同的作用域里的 "F" 引用了该闭包。该循环使得内
存不能被释放。
建议: 不要这么做。

<code class="note">注意</code> execute() 是如何用来执行 Ex 命令的。这不怎样好看。
在 Vim9 脚本中可用命令块，见  <a href="vim9.html#inline-function">inline-function</a> 。

尽管可以使用  <code class="badlink">for</code>  命令中的循环变量，在闭包调用时它必须仍然存在，否则会出错。
<b class="vimtag"> <a name="E1302">E1302</a> </b>

匿名函数表达式使用的内部名形如 '<code class="special">&lt;lambda&gt;</code>42'。如果有关于某匿名函数的错误，可以
用下述命令查看它的定义: 
<code class="example">        :function &lt;lambda&gt;42</code>
另见:  <a href="eval.html#numbered-function">numbered-function</a> 

</section><hr class="doubleline" /><section class=inner>
<h4>3. 内部变量                             <b class="vimtag"> <a name="internal-variables">internal-variables</a> </b> <b class="vimtag"> <a name="E461">E461</a> </b> <b class="vimtag"> <a name="E1001">E1001</a> </b></h4>
内部变量的名字由字母、数字和 '_' 组成。但不能由数字开始。老式脚本里也可以使用
花括号，见  <a href="eval.html#curly-braces-names">curly-braces-names</a> 。

老式脚本里内部变量通过 ":let" 命令建立  <a href="eval.html#:let">:let</a> 。内部变量通过 ":unlet" 命令显式
删除  <a href="eval.html#:unlet">:unlet</a> 。
使用非内部变量的名字或引用已经删除的内部变量会产生错误。

 <a href="vim9.html#Vim9">Vim9</a>  脚本里不使用  <a href="eval.html#:let">:let</a> ，变量的用法也不同，见  <a href="vim9.html#:var">:var</a> 。

                                                <b class="vimtag"> <a name="variable-scope">variable-scope</a> </b>
变量有不同的命名空间，根据附加的前缀决定:

                     (无) 函数内: 局部于函数；
                          老式脚本里: 全局；
                           <a href="vim9.html#Vim9">Vim9</a>  脚本里: 局部于脚本
 <a href="eval.html#buffer-variable">buffer-variable</a>     b:   局部于当前缓冲区。
 <a href="eval.html#window-variable">window-variable</a>     w:   局部于当前窗口。
 <a href="eval.html#tabpage-variable">tabpage-variable</a>    t:   局部于当前标签页。
 <a href="eval.html#global-variable">global-variable</a>     g:   全局。
 <a href="eval.html#local-variable">local-variable</a>      l:   局部于函数 (只限于老式函数内使用)。
 <a href="eval.html#script-variable">script-variable</a>     s:   局部于  <a href="repeat.html#:source">:source</a>  的 Vim 脚本。
 <a href="userfunc.html#function-argument">function-argument</a>   a:   函数参数 (只限于老式函数内使用)。
 <a href="eval.html#vim-variable">vim-variable</a>        v:   Vim 预定义的全局变量。

作用域本身可以用作  <a href="eval.html#Dictionary">Dictionary</a> 。例如，要删除所有局部于脚本的变量: 
<code class="example">        :for k in keys(s:)</code>
<code class="example">        :    unlet s:[k]</code>
<code class="example">        :endfor</code>

<code class="note">备注</code>: Vim9 脚本变量也可以局部于命令块，见  <a href="vim9.html#vim9-scopes">vim9-scopes</a> 。

                                                <b class="vimtag"> <a name="buffer-variable">buffer-variable</a> </b> <b class="vimtag"> <a name="b:var">b:var</a> </b> <b class="vimtag"> <a name="b:">b:</a> </b>
"b:" 开头的变量名局部于当前缓冲区。这样，你可以为每个缓冲区定义不同的 "b:foo"
变量。这种变量在缓冲区被删除时 (:bwipeout 或 :bdelete  <a href="windows.html#:bdelete">:bdelete</a> ) 同时被删除。

预定义了如下的缓冲区局部变量:
                                        <b class="vimtag"> <a name="b:changedtick">b:changedtick</a> </b> <b class="vimtag"> <a name="changetick">changetick</a> </b>
b:changedtick   当前缓冲区的改变次数。每次改变都会递增。撤销命令在此情形下也被
                视作一次改变。写入缓冲区后复位 <a href="options.html#'modified'">'modified'</a> 也算。
                这可用来在缓冲区发生改变时执行一些动作。比如: 
<code class="example">                    :if my_changedtick != b:changedtick</code>
<code class="example">                    : let my_changedtick = b:changedtick</code>
<code class="example">                    : call My_Update()</code>
<code class="example">                    :endif</code>
                不可改变或删除 b:changedtick 变量。

                                                <b class="vimtag"> <a name="window-variable">window-variable</a> </b> <b class="vimtag"> <a name="w:var">w:var</a> </b> <b class="vimtag"> <a name="w:">w:</a> </b>
"w:" 开头的变量名局部于当前窗口。窗口关闭时被删除。

                                                <b class="vimtag"> <a name="tabpage-variable">tabpage-variable</a> </b> <b class="vimtag"> <a name="t:var">t:var</a> </b> <b class="vimtag"> <a name="t:">t:</a> </b>
"t" 开始的变量名局部于当前标签页。标签页关闭时，这些变量被删除。
<code class="notvi">{仅当编译时加入  <a href="various.html#+windows">+windows</a>  特性才有效}</code>

                                                <b class="vimtag"> <a name="global-variable">global-variable</a> </b> <b class="vimtag"> <a name="g:var">g:var</a> </b> <b class="vimtag"> <a name="g:">g:</a> </b>
函数内部和  <a href="vim9.html#Vim9">Vim9</a>  脚本里，全局变量通过 "g:" 访问。不提供该前缀则会访问局部于函
数或局部于脚本的变量。当然在其他地方，如果你想的话也可以使用 "g:"。

                                                <b class="vimtag"> <a name="local-variable">local-variable</a> </b> <b class="vimtag"> <a name="l:var">l:var</a> </b> <b class="vimtag"> <a name="l:">l:</a> </b>
访问函数的局部变量无需任何前缀。但如果你想要，可以使用 "l:"。不过，如果没有
"l:" 前缀，你可能会和保留的变量名冲突。例如 "count"。它本身指代 "v:count"。但
使用了 "l:count" 你就可以使用同名的局部变量。


                                                <b class="vimtag"> <a name="script-variable">script-variable</a> </b> <b class="vimtag"> <a name="s:var">s:var</a> </b>
老式 Vim 脚本里，可以使用 "s:" 开头的变量。它们不能在脚本之外访问，因而可以称
为局部于脚本的变量。
 <a href="vim9.html#Vim9">Vim9</a>  脚本里 "s:" 前缀可以省略，因为缺省变量就是局部于脚本的。

它们可以用于:
- 载入脚本时执行的命令
- 脚本定义的函数
- 脚本定义的自动命令
- 脚本定义的函数和自动命令里定义的函数和自动命令 (递归)
- 脚本里定义的用户定义命令
但不能用在:
- 该脚本载入的其它脚本
- 映射
- 菜单
- 等等

脚本变量可以用来防止和全局变量名的冲突。看看这个例子: 
<code class="example"></code>
<code class="example">        let s:counter = 0</code>
<code class="example">        function MyCounter()</code>
<code class="example">          let s:counter = s:counter + 1</code>
<code class="example">          echo s:counter</code>
<code class="example">        endfunction</code>
<code class="example">        command Tick call MyCounter()</code>
<code class="example"></code>
你可以从任何脚本里启动 "Tick"，但那个脚本里的 "s:counter" 变量不会被改变，只有
在 "Tick" 定义所在脚本的 "s:counter" 才会。

另一个完成相同功能的例子: 
<code class="example"></code>
<code class="example">        let s:counter = 0</code>
<code class="example">        command Tick let s:counter = s:counter + 1 | echo s:counter</code>
<code class="example"></code>
如果调用函数或者启动用户定义命令，脚本变量的上下文设置为函数和命令定义所在的脚
本。

脚本变量也可用于脚本里定义的函数里定义的函数。例如: 
<code class="example"></code>
<code class="example">        let s:counter = 0</code>
<code class="example">        function StartCounting(incr)</code>
<code class="example">          if a:incr</code>
<code class="example">            function MyCounter()</code>
<code class="example">              let s:counter = s:counter + 1</code>
<code class="example">            endfunction</code>
<code class="example">          else</code>
<code class="example">            function MyCounter()</code>
<code class="example">              let s:counter = s:counter - 1</code>
<code class="example">            endfunction</code>
<code class="example">          endif</code>
<code class="example">        endfunction</code>
<code class="example"></code>
调用 StartCounting() 时，定义 MyCounter() 函数或者递增或者递减计数器。不管
StartCounting() 在哪里调用，s:counter 变量总可以在 MyCounter() 里访问。

如果相同的脚本多次执行，使用的是同一个脚本变量。只要 Vim 还在运行，就保持有
效。这可以用于维护计数: 
<code class="example"></code>
<code class="example">        if !exists("s:counter")</code>
<code class="example">          let s:counter = 1</code>
<code class="example">          echo "脚本首次执行"</code>
<code class="example">        else</code>
<code class="example">          let s:counter = s:counter + 1</code>
<code class="example">          echo "脚本现在执行了 " .. s:counter .. " 次"</code>
<code class="example">        endif</code>
<code class="example"></code>
<code class="note">注意</code> 这意味着 filetype 插件不能为每个缓冲区提供不同的脚本变量。这时应使用缓冲
区的局部变量  <a href="eval.html#b:var">b:var</a> 。


预定义的 VIM 变量:                              <b class="vimtag"> <a name="vim-variable">vim-variable</a> </b> <b class="vimtag"> <a name="v:var">v:var</a> </b> <b class="vimtag"> <a name="v:">v:</a> </b>
                                                        <b class="vimtag"> <a name="E963">E963</a> </b> <b class="vimtag"> <a name="E1063">E1063</a> </b>
有些变量可以被用户设置，但不能改变类型。

                                        <b class="vimtag"> <a name="v:argv">v:argv</a> </b> <b class="vimtag"> <a name="argv-variable">argv-variable</a> </b>
v:argv          调用 Vim 时的命令行参数。这是字符串列表。首项是 Vim 命令。
                 <a href="eval.html#v:progpath">v:progpath</a>  给出带完整路径的命令。

                                        <b class="vimtag"> <a name="v:beval_col">v:beval_col</a> </b> <b class="vimtag"> <a name="beval_col-variable">beval_col-variable</a> </b>
v:beval_col     鼠标指针所在的列号，即  <a href="eval.html#v:beval_lnum">v:beval_lnum</a>  行中的字节位置。
                仅当计算 <a href="options.html#'balloonexpr'">'balloonexpr'</a> 选项时有效。

                                        <b class="vimtag"> <a name="v:beval_bufnr">v:beval_bufnr</a> </b> <b class="vimtag"> <a name="beval_bufnr-variable">beval_bufnr-variable</a> </b>
v:beval_bufnr   鼠标指针所在的缓冲区号。仅当计算 <a href="options.html#'balloonexpr'">'balloonexpr'</a> 选项时有效。

                                        <b class="vimtag"> <a name="v:beval_lnum">v:beval_lnum</a> </b> <b class="vimtag"> <a name="beval_lnum-variable">beval_lnum-variable</a> </b>
v:beval_lnum    鼠标指针所在的行号。仅当计算 <a href="options.html#'balloonexpr'">'balloonexpr'</a> 选项时有效。

                                        <b class="vimtag"> <a name="v:beval_text">v:beval_text</a> </b> <b class="vimtag"> <a name="beval_text-variable">beval_text-variable</a> </b>
v:beval_text    鼠标指针所在或之后的文本。通常是一个单词，可用于调试 C 程序。
                此处用到 <a href="options.html#'iskeyword'">'iskeyword'</a>，但也包括此位置之前的句号和 "-&gt;"。如果在
                ']' 上，使用它之前的文本，包括匹配的 '[' 和它之前的单词。如果
                在单行的可视区域上，使用高亮文本。另见  <a href="cmdline.html#%3Ccexpr%3E">&lt;cexpr&gt;</a> 。
                仅当计算 <a href="options.html#'balloonexpr'">'balloonexpr'</a> 选项时有效。

                                        <b class="vimtag"> <a name="v:beval_winnr">v:beval_winnr</a> </b> <b class="vimtag"> <a name="beval_winnr-variable">beval_winnr-variable</a> </b>
v:beval_winnr   鼠标指针所在的窗口号。仅当计算 <a href="options.html#'balloonexpr'">'balloonexpr'</a> 选项时有效。首个
                窗口的编号为零 (这和多数需要窗口编号的地方不同)。

                                        <b class="vimtag"> <a name="v:beval_winid">v:beval_winid</a> </b> <b class="vimtag"> <a name="beval_winid-variable">beval_winid-variable</a> </b>
v:beval_winid   鼠标指针所在的窗口 ID  <a href="windows.html#window-ID">window-ID</a> 。其它类同于 v:beval_winnr。

                                        <b class="vimtag"> <a name="v:char">v:char</a> </b> <b class="vimtag"> <a name="char-variable">char-variable</a> </b>
v:char          计算 <a href="options.html#'formatexpr'">'formatexpr'</a> 时使用的参数和用于带 <code class="special">&lt;expr&gt;</code> 的缩写中输入的字
                符  <a href="map.html#:map-%3Cexpr%3E">:map-&lt;expr&gt;</a> 。
                也用于  <a href="autocmd.html#InsertCharPre">InsertCharPre</a>  和  <a href="autocmd.html#InsertEnter">InsertEnter</a>  事件。

                        <b class="vimtag"> <a name="v:charconvert_from">v:charconvert_from</a> </b> <b class="vimtag"> <a name="charconvert_from-variable">charconvert_from-variable</a> </b>
v:charconvert_from
                要转换的文件字符编码名。只在计算 <a href="options.html#'charconvert'">'charconvert'</a> 选项时有效。

                        <b class="vimtag"> <a name="v:charconvert_to">v:charconvert_to</a> </b> <b class="vimtag"> <a name="charconvert_to-variable">charconvert_to-variable</a> </b>
v:charconvert_to
                转换后的文件字符编码名。只在计算 <a href="options.html#'charconvert'">'charconvert'</a> 选项时有效。

                                        <b class="vimtag"> <a name="v:cmdarg">v:cmdarg</a> </b> <b class="vimtag"> <a name="cmdarg-variable">cmdarg-variable</a> </b>
v:cmdarg        该变量有两个目的:
                1. 文件读写命令的额外参数。目前，它们包括 "++enc=" 和
                   "++ff="。该变量在文件读写命令的自动命令事件激活之前设置。开
                   头有一个空格，以便直接把该变量附加到读写命令之后。<code class="note">注意</code>: 这
                   里不包括 "+cmd" 参数，因为它总要被执行的。
                2. 使用 ":hardcopy" 打印 PostScript 文件时，":hardcopy" 命令的
                   参数。在 <a href="options.html#'printexpr'">'printexpr'</a> 里用得到。

                                        <b class="vimtag"> <a name="v:cmdbang">v:cmdbang</a> </b> <b class="vimtag"> <a name="cmdbang-variable">cmdbang-variable</a> </b>
v:cmdbang       文件读写命令时，和 v:cmdarg 设置的时间类似。如果使用了 "!"，其
                值为 1，不然为 0。<code class="note">注意</code> 它只能用于自动命令。用户命令里可以用
                 <a href="map.html#%3Cbang%3E">&lt;bang&gt;</a> 。
                                                <b class="vimtag"> <a name="v:collate">v:collate</a> </b> <b class="vimtag"> <a name="collate-variable">collate-variable</a> </b>
v:collate       运行时环境当前 locale 设置的排序规则。这使 Vim 脚本可访问当前
                locale 的编码。技术上: 这是 LC_COLLATE 的值。没有 locale 时的
                值为 "C"。
                此变量不能直接设置，请用  <a href="mlang.html#:language">:language</a>  命令。
                见  <a href="mlang.html#multi-lang">multi-lang</a> 。

                                                                <b class="vimtag"> <a name="v:colornames">v:colornames</a> </b>
v:colornames    映射色彩名对十六进色彩字符串的字典。色彩名可用于
                 <a href="syntax.html#highlight-guifg">highlight-guifg</a> 、 <a href="syntax.html#highlight-guibg">highlight-guibg</a>  和  <a href="syntax.html#highlight-guisp">highlight-guisp</a>  的参
                数。更新 v:colornames 里的项目不会立即影响语法高亮有影响。高亮
                命令 (可能由色彩方案脚本提供) 需要重新进行计算以更新色彩值。例
                如: 
<code class="example"></code>
<code class="example">                    :let v:colornames['fuscia'] = '#cf3ab4'</code>
<code class="example">                    :let v:colornames['mauve'] = '#915f6d'</code>
<code class="example">                    :highlight Normal guifg=fuscia guibg=mauve</code>

                不能用来覆盖  <a href="syntax.html#cterm-colors">cterm-colors</a>  ，但可以覆盖其他颜色。例如，
                 <code class="badlink">colors/lists/default.vim</code>  (之前在  <a href="gui_w32.html#rgb.txt">rgb.txt</a>  里定义) 里定义的
                X11 颜色。在插件里定义新色彩名时，建议仅当色彩尚不存在时设置色
                彩项目。例如: 
<code class="example"></code>
<code class="example">                    :call extend(v:colornames, {</code>
<code class="example">                        \ 'fuscia': '#cf3ab4',</code>
<code class="example">                        \ 'mauve': '#915f6d,</code>
<code class="example">                        \ }, 'keep')</code>

                带 <code class="badlink">'keep'</code> 选项的  <a href="builtin.html#extend()">extend()</a>  仅当  <a href="eval.html#v:colornames">v:colornames</a>  不存在某色彩时
                加入该色彩。这样用户在  <a href="starting.html#.vimrc">.vimrc</a>  里可以选择常用名的准确色彩值。

                可以从此字典里删除项目，但 <code class="emphasis">不</code> 建议如此，因为会破坏其他脚本的效
                果。而且可能也不能达成你想要的，因为  <a href="syntax.html#:colorscheme">:colorscheme</a>  和
                 <a href="syntax.html#:highlight">:highlight</a>  命令两者都会自动载入  <code class="badlink">colors/lists/default.vim</code> 
                里的所有色彩脚本。

                                <b class="vimtag"> <a name="v:completed_item">v:completed_item</a> </b> <b class="vimtag"> <a name="completed_item-variable">completed_item-variable</a> </b>
v:completed_item
                包含  <a href="insert.html#complete-items">complete-items</a>  的  <a href="eval.html#Dictionary">Dictionary</a> ，用于得到  <a href="autocmd.html#CompleteDone">CompleteDone</a> 
                之后的最近补全。如果补全失败， <a href="eval.html#Dictionary">Dictionary</a>  为空。
                <code class="note">注意</code>: 插件可以修改本值以模拟内建的  <a href="autocmd.html#CompleteDone">CompleteDone</a>  事件行为。

                                        <b class="vimtag"> <a name="v:count">v:count</a> </b> <b class="vimtag"> <a name="count-variable">count-variable</a> </b>
v:count         最近的普通模式命令使用的计数。在映射前可用于得到计数。只读。
                例如: 
<code class="example">        :map _x :&lt;C-U&gt;echo "计数为 " .. v:count&lt;CR&gt;</code>
                <code class="note">注意</code>: <code class="special">&lt;C-U&gt;</code> 是必要的，它删除紧跟在计数之后 ':' 所给出的行范
                围。
                如果有两个计数，如 "3d2w"，它们进行相乘，如同命令行实际发生的
                那样，等同于 "d6w"。
                也用于计算 <a href="options.html#'formatexpr'">'formatexpr'</a> 选项。
                为了后向兼容，这里也可以用 "count"，除非  <a href="eval.html#scriptversion">scriptversion</a>  为 3
                或更高。

                                        <b class="vimtag"> <a name="v:count1">v:count1</a> </b> <b class="vimtag"> <a name="count1-variable">count1-variable</a> </b>
v:count1        类似于 "v:count"，但没有给出计数时，缺省为 1。

                                                <b class="vimtag"> <a name="v:ctype">v:ctype</a> </b> <b class="vimtag"> <a name="ctype-variable">ctype-variable</a> </b>
v:ctype         运行环境当前的字符 locale 设置。它使得 Vim 脚本能得到当前的
                locale 编码。技术细节: 这就是 LC_CTYPE 的值。如果没有使用
                locale，其值为 "C"。
                该变量不能直接设置，请使用  <a href="mlang.html#:language">:language</a>  命令。
                见  <a href="mlang.html#multi-lang">multi-lang</a> 。

                                        <b class="vimtag"> <a name="v:dying">v:dying</a> </b> <b class="vimtag"> <a name="dying-variable">dying-variable</a> </b>
v:dying         通常为零。如果捕获到某个 "致命" 的 signal，设为 1。如果同时捕
                获到多个 signal，其值相应增加。在自动命令里可以用来检查 Vim
                是否被异常终止。<code class="notvi">{仅限于 Unix}</code>
                例如: 
<code class="example">        :au VimLeave * if v:dying | echo "\nAAAAaaaarrrggghhhh!!!\n" | endif</code>
                <code class="note">备注</code>: 如果 v:dying 为一而同时又捕捉到另一个致命的 signal，不执
                行 VimLeave 自动命令。

                                        <b class="vimtag"> <a name="v:exiting">v:exiting</a> </b> <b class="vimtag"> <a name="exiting-variable">exiting-variable</a> </b>
v:exiting       Vim 退出码。通常为零，非零代表出现某种错误。调用  <a href="autocmd.html#VimLeavePre">VimLeavePre</a> 
                和  <a href="autocmd.html#VimLeave">VimLeave</a>  自动命令前，此值为 v:null。见  <a href="editing.html#:q">:q</a> 、 <a href="editing.html#:x">:x</a>  和
                 <a href="quickfix.html#:cquit">:cquit</a> 。
                示例: 
<code class="example">                        :au VimLeave * echo "Exit value is " .. v:exiting</code>

                                        <b class="vimtag"> <a name="v:echospace">v:echospace</a> </b> <b class="vimtag"> <a name="echospace-variable">echospace-variable</a> </b>
v:echospace     在屏幕行末行上  <a href="eval.html#:echo">:echo</a>  消息不引发  <a href="message.html#hit-enter-prompt">hit-enter-prompt</a>  最多可用
                的屏幕单元格数目。取决于 <a href="options.html#'showcmd'">'showcmd'</a>、<a href="options.html#'ruler'">'ruler'</a> 和 <a href="options.html#'columns'">'columns'</a>。需要
                检查 <a href="options.html#'cmdheight'">'cmdheight'</a> 看看在末行之上是否有全宽的行存在。

                                        <b class="vimtag"> <a name="v:errmsg">v:errmsg</a> </b> <b class="vimtag"> <a name="errmsg-variable">errmsg-variable</a> </b>
v:errmsg        最近给出的错误信息。该变量可以设置。
                例如: 
<code class="example">        :let v:errmsg = ""</code>
<code class="example">        :silent! next</code>
<code class="example">        :if v:errmsg != ""</code>
<code class="example">        :  ... handle error</code>
                为了后向兼容，这里也可以用 "errmsg"，除非  <a href="eval.html#scriptversion">scriptversion</a>  为 3
                或更高。

                                <b class="vimtag"> <a name="v:errors">v:errors</a> </b> <b class="vimtag"> <a name="errors-variable">errors-variable</a> </b> <b class="vimtag"> <a name="assert-return">assert-return</a> </b>
v:errors        assert 函数找到的错误，如  <a href="testing.html#assert_true()">assert_true()</a> 。
                是一个字符串列表。
                assert 函数在 assert 失败后附加项目。
                返回值说明这一点: 如果有项目加入 v:errors，返回一，不然返回
                零。
                要清空旧的结果: 
<code class="example">        :let v:errors = []</code>
                如果用非列表来设置 v:errors，assert 函数会把它变成空列表。

                                        <b class="vimtag"> <a name="v:event">v:event</a> </b> <b class="vimtag"> <a name="event-variable">event-variable</a> </b>
v:event         包含当前  <a href="autocmd.html#autocommand">autocommand</a>  信息的字典。字典放置的内容参见具体事
                件。

                 <a href="autocmd.html#autocommand">autocommand</a>  结束后该字典清空，请参见  <a href="eval.html#dict-identity">dict-identity</a>  来了解
                如何取得字典独立的备份。如果你要在事件触发后保留信息，可用
                 <a href="builtin.html#deepcopy()">deepcopy()</a> 。例如: 
<code class="example">                        au TextYankPost * let g:foo = deepcopy(v:event)</code>


                                        <b class="vimtag"> <a name="v:exception">v:exception</a> </b> <b class="vimtag"> <a name="exception-variable">exception-variable</a> </b>
v:exception     最近捕获且没有完成的例外的值。见  <a href="eval.html#v:throwpoint">v:throwpoint</a>  和
                 <a href="eval.html#throw-variables">throw-variables</a> 。
                例如: 
<code class="example">        :try</code>
<code class="example">        :  throw "oops"</code>
<code class="example">        :catch /.*/</code>
<code class="example">        :  echo "caught" .. v:exception</code>
<code class="example">        :endtry</code>
                输出: "caught oops"。

                                        <b class="vimtag"> <a name="v:false">v:false</a> </b> <b class="vimtag"> <a name="false-variable">false-variable</a> </b>
v:false         取值为零的数值。用于在 JSON 里填入 "false"。见
                 <a href="builtin.html#json_encode()">json_encode()</a> 。
                用于字符串时会返回 "v:false"。 
<code class="example">                        echo v:false</code>
<code class="section">                        v:false </code>
                这样 eval() 可以把该字符串解析回相同的值。只读。
                 <a href="vim9.html#Vim9">Vim9</a>  脚本里可用布尔型的 "false" 值。

                                        <b class="vimtag"> <a name="v:fcs_reason">v:fcs_reason</a> </b> <b class="vimtag"> <a name="fcs_reason-variable">fcs_reason-variable</a> </b>
v:fcs_reason    激活  <a href="autocmd.html#FileChangedShell">FileChangedShell</a>  事件的原因。
                可以在自动命令里用来决定该做什么和/或如何设置 v:fcs_choice。可
                能的值是:
                        deleted         文件不再存在
                        conflict        文件内容、模式或修改时间被改变，而缓冲
                                        区同时被修改
                        changed         文件内容被改变
                        mode            文件模式被改变
                        time            文件修改时间被改变

                                        <b class="vimtag"> <a name="v:fcs_choice">v:fcs_choice</a> </b> <b class="vimtag"> <a name="fcs_choice-variable">fcs_choice-variable</a> </b>
v:fcs_choice     <a href="autocmd.html#FileChangedShell">FileChangedShell</a>  事件激活后该做什么。可以在自动命令里用来告
                诉 Vim 如何处理涉及的缓冲区:
                        reload          重新载入缓冲区 (如果文件已删除，不能工
                                        作)。
                        edit            重新载入缓冲区并检测 <a href="options.html#'fileformat'">'fileformat'</a>、
                                        <a href="options.html#'fileencoding'">'fileencoding'</a>、<a href="options.html#'binary'">'binary'</a> 等选项的值
                                        (如果文件已删除，不能工作)。
                        ask             询问用户该做什么，就像没有自动命令一
                                        样。不过，如果只有修改时间被改变，不做
                                        任何事。
                        &lt;空&gt;            不做任何事。自动命令应该已经处理完毕。
                缺省为空。如果使用别的 (非法的) 值，Vim 的行为就像它为空一样。
                不会有<code class="note">警告</code>信息。

                                        <b class="vimtag"> <a name="v:fname">v:fname</a> </b> <b class="vimtag"> <a name="fname-variable">fname-variable</a> </b>
v:fname         计算 <a href="options.html#'includeexpr'">'includeexpr'</a> 时: 检测到的文件名。否则为空。

                                        <b class="vimtag"> <a name="v:fname_in">v:fname_in</a> </b> <b class="vimtag"> <a name="fname_in-variable">fname_in-variable</a> </b>
v:fname_in      输入文件名。在计算以下选项时合法:
<code class="section">                        选项            用于 </code>
                        <a href="options.html#'charconvert'">'charconvert'</a>   要转换的文件
                        <a href="options.html#'diffexpr'">'diffexpr'</a>      原始文件
                        <a href="options.html#'patchexpr'">'patchexpr'</a>     原始文件
                        <a href="options.html#'printexpr'">'printexpr'</a>     要打印的文件
                 <a href="autocmd.html#SwapExists">SwapExists</a>  里设为交换文件名。

                                        <b class="vimtag"> <a name="v:fname_out">v:fname_out</a> </b> <b class="vimtag"> <a name="fname_out-variable">fname_out-variable</a> </b>
v:fname_out     输出文件名。只有在计算以下选项时才合法:
<code class="section">                        选项            用于 </code>
                        <a href="options.html#'charconvert'">'charconvert'</a>   生成的转换完成的文件 (*)
                        <a href="options.html#'diffexpr'">'diffexpr'</a>      diff 的结果
                        <a href="options.html#'patchexpr'">'patchexpr'</a>     产生的补丁文件
                (*) 如果用于为写入命令进行转换 (比如，":w file")，等价于
                v:fname_in。如果用于为读入命令进行转换 (比如，":e file")，它是
                一个临时文件名，和 v:fname_in 不同。

                                        <b class="vimtag"> <a name="v:fname_new">v:fname_new</a> </b> <b class="vimtag"> <a name="fname_new-variable">fname_new-variable</a> </b>
v:fname_new     文件新版本的名字。只有在计算 <a href="options.html#'diffexpr'">'diffexpr'</a> 的时候才有效。

                                        <b class="vimtag"> <a name="v:fname_diff">v:fname_diff</a> </b> <b class="vimtag"> <a name="fname_diff-variable">fname_diff-variable</a> </b>
v:fname_diff    比较结果 (或补丁) 的文件名。只有在计算 <a href="options.html#'patchexpr'">'patchexpr'</a> 的时候才有
                效。

                                        <b class="vimtag"> <a name="v:folddashes">v:folddashes</a> </b> <b class="vimtag"> <a name="folddashes-variable">folddashes-variable</a> </b>
v:folddashes    用于 <a href="options.html#'foldtext'">'foldtext'</a>: 反映关闭的折叠的折叠级别的连字符。
                 <a href="eval.html#sandbox">sandbox</a>  里只读。 <a href="fold.html#fold-foldtext">fold-foldtext</a> 

                                        <b class="vimtag"> <a name="v:foldlevel">v:foldlevel</a> </b> <b class="vimtag"> <a name="foldlevel-variable">foldlevel-variable</a> </b>
v:foldlevel     用于 <a href="options.html#'foldtext'">'foldtext'</a>: 关闭的折叠的折叠级别。
                 <a href="eval.html#sandbox">sandbox</a>  里只读。 <a href="fold.html#fold-foldtext">fold-foldtext</a> 

                                        <b class="vimtag"> <a name="v:foldend">v:foldend</a> </b> <b class="vimtag"> <a name="foldend-variable">foldend-variable</a> </b>
v:foldend       用于 <a href="options.html#'foldtext'">'foldtext'</a>: 关闭的折叠的最后一行。
                 <a href="eval.html#sandbox">sandbox</a>  里只读。 <a href="fold.html#fold-foldtext">fold-foldtext</a> 

                                        <b class="vimtag"> <a name="v:foldstart">v:foldstart</a> </b> <b class="vimtag"> <a name="foldstart-variable">foldstart-variable</a> </b>
v:foldstart     用于 <a href="options.html#'foldtext'">'foldtext'</a>: 关闭的折叠的第一行。
                 <a href="eval.html#sandbox">sandbox</a>  里只读。 <a href="fold.html#fold-foldtext">fold-foldtext</a> 

                                        <b class="vimtag"> <a name="v:hlsearch">v:hlsearch</a> </b> <b class="vimtag"> <a name="hlsearch-variable">hlsearch-variable</a> </b>
v:hlsearch      用于指定搜索高亮是否打开的变量。只有在启动 <a href="options.html#'hlsearch'">'hlsearch'</a> 时它的设
                置才有意义，这需要  <a href="various.html#+extra_search">+extra_search</a> 。设置该变量为零相当
                 <a href="pattern.html#:nohlsearch">:nohlsearch</a>  命令，设置为一则相当于 
<code class="example">                        let &amp;hlsearch = &amp;hlsearch</code>
                <code class="note">备注</code> 函数返回时复原其值。 <a href="userfunc.html#function-search-undo">function-search-undo</a> 。

                                        <b class="vimtag"> <a name="v:insertmode">v:insertmode</a> </b> <b class="vimtag"> <a name="insertmode-variable">insertmode-variable</a> </b>
v:insertmode    用于  <a href="autocmd.html#InsertEnter">InsertEnter</a>  和  <a href="autocmd.html#InsertChange">InsertChange</a>  自动命令事件。取值:
                        i       插入模式
                        r       替换模式
                        v       虚拟替换模式

                                                <b class="vimtag"> <a name="v:key">v:key</a> </b> <b class="vimtag"> <a name="key-variable">key-variable</a> </b>
v:key            <a href="eval.html#Dictionary">Dictionary</a>  里当前项目的键。只有在  <a href="builtin.html#map()">map()</a>  和  <a href="builtin.html#filter()">filter()</a>  里计
                算表达式时有效。
                只读。

                                                <b class="vimtag"> <a name="v:lang">v:lang</a> </b> <b class="vimtag"> <a name="lang-variable">lang-variable</a> </b>
v:lang          运行环境当前的消息 locale 设置。它使得 Vim 脚本能得到当前使用
                的语言。技术细节: 这就是 LC_MESSAGES 的值。该值和系统有关。
                该变量不能直接设置，请使用  <a href="mlang.html#:language">:language</a>  命令。
                它和  <a href="eval.html#v:ctype">v:ctype</a>  不同，因为消息可能使用不同于字符编码的语言。见
                 <a href="mlang.html#multi-lang">multi-lang</a> 。

                                                <b class="vimtag"> <a name="v:lc_time">v:lc_time</a> </b> <b class="vimtag"> <a name="lc_time-variable">lc_time-variable</a> </b>
v:lc_time       运行环境当前的时间消息 locale 设置。它使得 Vim
                脚本能得到当前使用的语言。技术细节: 这就是 LC_TIME 的值。
                该变量不能直接设置，请使用  <a href="mlang.html#:language">:language</a>  命令。见  <a href="mlang.html#multi-lang">multi-lang</a> 。

                                                <b class="vimtag"> <a name="v:lnum">v:lnum</a> </b> <b class="vimtag"> <a name="lnum-variable">lnum-variable</a> </b>
v:lnum          <a href="options.html#'foldexpr'">'foldexpr'</a>  <a href="fold.html#fold-expr">fold-expr</a> 、<a href="options.html#'formatexpr'">'formatexpr'</a> 和 <a href="options.html#'indentexpr'">'indentexpr'</a> 表达式中
                的行号和 <a href="options.html#'guitablabel'">'guitablabel'</a> 和 <a href="options.html#'guitabtooltip'">'guitabtooltip'</a> 中的标签页号。只有在
                计算这些表达式时才合法。在  <a href="eval.html#sandbox">sandbox</a>  里时只读。

                                                <b class="vimtag"> <a name="v:maxcol">v:maxcol</a> </b> <b class="vimtag"> <a name="maxcol-variable">maxcol-variable</a> </b>
v:maxcol        最大行长。取决于使用之外，可以指屏幕列，字符或字节数。当前所有
                系统上其值都为 2147483647。

                                        <b class="vimtag"> <a name="v:mouse_win">v:mouse_win</a> </b> <b class="vimtag"> <a name="mouse_win-variable">mouse_win-variable</a> </b>
v:mouse_win     用  <a href="builtin.html#getchar()">getchar()</a>  得到鼠标点击时所在的窗口号。首个窗口的编号为
                1 ，就像  <a href="builtin.html#winnr()">winnr()</a>  那样。如果那时没有鼠标点击，该值为零。

                                        <b class="vimtag"> <a name="v:mouse_winid">v:mouse_winid</a> </b> <b class="vimtag"> <a name="mouse_winid-variable">mouse_winid-variable</a> </b>
v:mouse_winid   用  <a href="builtin.html#getchar()">getchar()</a>  得到鼠标点击时所在的窗口 ID。如果那时没有鼠标点
                击，该值为零。

                                        <b class="vimtag"> <a name="v:mouse_lnum">v:mouse_lnum</a> </b> <b class="vimtag"> <a name="mouse_lnum-variable">mouse_lnum-variable</a> </b>
v:mouse_lnum    用  <a href="builtin.html#getchar()">getchar()</a>  得到鼠标点击时所在的行号。这是文本行号，不是屏
                幕行号。如果那时没有鼠标点击，该值为零。

                                        <b class="vimtag"> <a name="v:mouse_col">v:mouse_col</a> </b> <b class="vimtag"> <a name="mouse_col-variable">mouse_col-variable</a> </b>
v:mouse_col     用  <a href="builtin.html#getchar()">getchar()</a>  得到鼠标点击时所在的列号。这是屏幕列号，就像
                 <a href="builtin.html#virtcol()">virtcol()</a>  那样。如果那时没有鼠标点击，该值为零。

                                        <b class="vimtag"> <a name="v:none">v:none</a> </b> <b class="vimtag"> <a name="none-variable">none-variable</a> </b> <b class="vimtag"> <a name="None">None</a> </b>
v:none          空字符串。用于在 JSON 里填入空项目。见  <a href="builtin.html#json_encode()">json_encode()</a> 。
                也可用于函数参数，指代缺省值，见  <a href="userfunc.html#none-function_argument">none-function_argument</a> 。
                用于数值时返回零。
                用于字符串时会返回 "v:none"。 
<code class="example">                        echo v:none</code>
<code class="section">                        v:none </code>
                这样 eval() 可以把该字符串解析回相同的值。只读。
                <code class="note">注意</code> 使用 `== v:none` 和 `!= v:none` 常会报错。应该使用
                `is v:none` 和 `isnot v:none`。

                                        <b class="vimtag"> <a name="v:null">v:null</a> </b> <b class="vimtag"> <a name="null-variable">null-variable</a> </b>
v:null          空字符串。用于在 JSON 里填入 "null"。见  <a href="builtin.html#json_encode()">json_encode()</a> 。
                用于数值时返回零。
                用于字符串时会返回 "v:null"。 
<code class="example">                        echo v:null</code>
<code class="section">                        v:null </code>
                这样 eval() 可以把该字符串解析回相同的值。只读。
                 <a href="vim9.html#Vim9">Vim9</a>  脚本里用  <a href="vim9.html#null">null</a>  时可以不带 "v:"。
                有的地方  <a href="eval.html#v:null">v:null</a>  和  <a href="vim9.html#null">null</a>  可用于未设置过的列表、字典、作业
                等。这和空列表、字典等略有不同。

                                        <b class="vimtag"> <a name="v:numbermax">v:numbermax</a> </b> <b class="vimtag"> <a name="numbermax-variable">numbermax-variable</a> </b>
v:numbermax     数值的最大值。

                                        <b class="vimtag"> <a name="v:numbermin">v:numbermin</a> </b> <b class="vimtag"> <a name="numbermin-variable">numbermin-variable</a> </b>
v:numbermin     数值的最小值 (为负数)。

                                        <b class="vimtag"> <a name="v:numbersize">v:numbersize</a> </b> <b class="vimtag"> <a name="numbersize-variable">numbersize-variable</a> </b>
v:numbersize    数值型的位数。通常为 64，但在某些系统上可能为 32。

                                        <b class="vimtag"> <a name="v:oldfiles">v:oldfiles</a> </b> <b class="vimtag"> <a name="oldfiles-variable">oldfiles-variable</a> </b>
v:oldfiles      启动时从  <a href="starting.html#viminfo">viminfo</a>  文件载入的文件名列表。Vim 记住的位置标记所
                在的就是这些文件。列表长度的上限由 <a href="options.html#'viminfo'">'viminfo'</a> 选项的 ' 参数定义
                (缺省是 100)。
                如果不用  <a href="starting.html#viminfo">viminfo</a> ，该列表为空。
                另见  <a href="starting.html#:oldfiles">:oldfiles</a>  和  <a href="cmdline.html#c_%23%3C">c_#&lt;</a> 。
                此列表可修改，但并不影响之后  <a href="starting.html#viminfo">viminfo</a>  文件保存什么。同时，如
                果使用非字符串的值，会有问题。
                <code class="notvi">{仅当编译时加入  <a href="various.html#+viminfo">+viminfo</a>  特性才有效}</code>

                                                    <b class="vimtag"> <a name="v:option_new">v:option_new</a> </b>
v:option_new    选项的新值。执行  <a href="autocmd.html#OptionSet">OptionSet</a>  自动命令时有效。
                                                    <b class="vimtag"> <a name="v:option_old">v:option_old</a> </b>
v:option_old    选项的旧值。执行  <a href="autocmd.html#OptionSet">OptionSet</a>  自动命令时有效。取决于用来设置的
                命令和选项的类型，这可以是旧的局部值，也可以是旧的全局值。
                                                    <b class="vimtag"> <a name="v:option_oldlocal">v:option_oldlocal</a> </b>
v:option_oldlocal
                选项的旧的局部值。执行  <a href="autocmd.html#OptionSet">OptionSet</a>  自动命令时有效。
                                                    <b class="vimtag"> <a name="v:option_oldglobal">v:option_oldglobal</a> </b>
v:option_oldglobal
                选项的旧的全部值。执行  <a href="autocmd.html#OptionSet">OptionSet</a>  自动命令时有效。
                                                    <b class="vimtag"> <a name="v:option_type">v:option_type</a> </b>
v:option_type   设置命令的作用域。执行  <a href="autocmd.html#OptionSet">OptionSet</a>  自动命令时有效。可能为
                "global" 或 "local"
                                                    <b class="vimtag"> <a name="v:option_command">v:option_command</a> </b>
v:option_command
                用于设置选项的命令。执行  <a href="autocmd.html#OptionSet">OptionSet</a>  自动命令时有效。
<code class="section">                        值              选项设置方法   </code>
                        "setlocal"       <a href="options.html#:setlocal">:setlocal</a>  或 ":let l:xxx"
                        "setglobal"      <a href="options.html#:setglobal">:setglobal</a>  或 ":let g:xxx"
                        "set"            <a href="options.html#:set">:set</a>  或  <a href="eval.html#:let">:let</a> 
                        "modeline"       <a href="options.html#modeline">modeline</a> 
                                        <b class="vimtag"> <a name="v:operator">v:operator</a> </b> <b class="vimtag"> <a name="operator-variable">operator-variable</a> </b>
v:operator      普通模式给出的最近的操作符。除了 <code class="special">&lt;g&gt;</code> 或 <code class="special">&lt;z&gt;</code> 开始的命令是两个
                字符外，这是单个字符。最好和  <a href="eval.html#v:prevcount">v:prevcount</a>  和  <a href="eval.html#v:register">v:register</a>  一
                起使用。常常，先中止操作符等待模式，然后使用操作符，例如: 
<code class="example">                        :omap O &lt;Esc&gt;:call MyMotion(v:operator)&lt;CR&gt;</code>
                直到输入下一个操作符之前，该值保持不变。因此不要期待该值会为
                空。
                 <a href="change.html#:delete">:delete</a> 、 <a href="change.html#:yank">:yank</a>  或其它 Ex 命令不改变 v:operator。
                只读。

                                        <b class="vimtag"> <a name="v:prevcount">v:prevcount</a> </b> <b class="vimtag"> <a name="prevcount-variable">prevcount-variable</a> </b>
v:prevcount     倒数第二次的普通模式命令使用的计数，也就是再上一个命令用的
                v:count 的值。可以用来先中止可视模式或操作符等待模式，然后使用
                计数。 
<code class="example">                        :vmap % &lt;Esc&gt;:call MyFilter(v:prevcount)&lt;CR&gt;</code>
                只读。

                                        <b class="vimtag"> <a name="v:profiling">v:profiling</a> </b> <b class="vimtag"> <a name="profiling-variable">profiling-variable</a> </b>
v:profiling     通常为零。开始用 ":profile start" 之后设为一。见  <a href="repeat.html#profiling">profiling</a> 。

                                        <b class="vimtag"> <a name="v:progname">v:progname</a> </b> <b class="vimtag"> <a name="progname-variable">progname-variable</a> </b>
v:progname      包含 Vim 启动时使用的名字 (路径已被去掉)。可以用来为  <a href="starting.html#view">view</a> 、
                 <a href="starting.html#evim">evim</a>  等符号链接到 Vim 的名字提供特殊的设置。
                只读。

                                        <b class="vimtag"> <a name="v:progpath">v:progpath</a> </b> <b class="vimtag"> <a name="progpath-variable">progpath-variable</a> </b>
v:progpath      包含 Vim 启动时使用的命令，使用的形式如果传递给外壳的话会保证
                和当前进程运行相同的 Vim 可执行程序 (如果 $PATH 没变的话)。可
                用于通过  <a href="remote.html#--remote-expr">--remote-expr</a>  给 Vim 服务器发消息。
                要得到完整路径: 
<code class="example">                        echo exepath(v:progpath)</code>
                如果命令使用相对路径，这样就会把相对路径扩展为完整路径，从而可
                在  <a href="editing.html#:cd">:cd</a>  后使用。假定用 "./vim" 启动，返回
                "/home/user/path/to/vim/src/vim"。
                Linux 和其它系统上总是使用完整路径。
                Mac 上可能只是 "vim"，如上所述使用 exepath() 可用来得到完整路
                径。
                MS-Windows 上的可执行文件可能叫做 "vim.exe"，但 v:progpath 中
                不会带上 ".exe"。
                只读。

                                        <b class="vimtag"> <a name="v:register">v:register</a> </b> <b class="vimtag"> <a name="register-variable">register-variable</a> </b>
v:register      当前的普通模式命令使用的寄存器名字 (不管该命令是否使用寄存
                器)，也用于当前执行的普通模式的映射 (用于其中的接受寄存器的自
                定义命令)。
                如果没有特殊指定，使用缺省寄存器 '"'。除非 <a href="options.html#'clipboard'">'clipboard'</a> 包含
                "unamed" 或 "unamedplus"，此时它为 '*' 或 '+'。
                另见  <a href="builtin.html#getreg()">getreg()</a>  和  <a href="builtin.html#setreg()">setreg()</a> 

                                        <b class="vimtag"> <a name="v:scrollstart">v:scrollstart</a> </b> <b class="vimtag"> <a name="scrollstart-variable">scrollstart-variable</a> </b>
v:scrollstart   指示使屏幕上滚的脚本或函数的字符串。只有在原来为空时才设置，因
                此只记住第一个原因。如果来自输入的命令，设为 "Unknown"。
                可以用来发现你的脚本为什么产生 hit-enter 提示。

                                        <b class="vimtag"> <a name="v:servername">v:servername</a> </b> <b class="vimtag"> <a name="servername-variable">servername-variable</a> </b>
v:servername    如果有的话，注册过的  <a href="remote.html#client-server-name">client-server-name</a>  名字。
                只读。


v:searchforward                 <b class="vimtag"> <a name="v:searchforward">v:searchforward</a> </b> <b class="vimtag"> <a name="searchforward-variable">searchforward-variable</a> </b>
                搜索方向: 正向搜索后为 1，反向搜索后为 0。直接设置最近搜索模式
                会复位此值为正向，见  <a href="change.html#quote%2F">quote/</a> 。
                <code class="note">注意</code> 从函数返回时该值被复原  <a href="userfunc.html#function-search-undo">function-search-undo</a> 。
                可读写。

                                        <b class="vimtag"> <a name="v:shell_error">v:shell_error</a> </b> <b class="vimtag"> <a name="shell_error-variable">shell_error-variable</a> </b>
v:shell_error   最近一次外壳命令的返回值。如果非零，最近一次外壳命令有错。如果
                为零，则该命令成功返回。这只有在外壳把错误代码返回给 Vim 的时
                候才工作。-1 通常用来告知该命令无法执行。只读。
                例如: 
<code class="example">        :!mv foo bar</code>
<code class="example">        :if v:shell_error</code>
<code class="example">        :  echo '不能把 "foo" 换名为 "bar"!'</code>
<code class="example">        :endif</code>
                为了后向兼容，这里也可以用 "shell_error"，除非  <a href="eval.html#scriptversion">scriptversion</a> 
                为 3 或更高。

                                        <b class="vimtag"> <a name="v:sizeofint">v:sizeofint</a> </b> <b class="vimtag"> <a name="sizeofint-variable">sizeofint-variable</a> </b>
v:sizeofint     一个 int 值的字节数。取决于 Vim 的编译环境。只对决定测试会否给
                出期待中的结果有用。

                                        <b class="vimtag"> <a name="v:sizeoflong">v:sizeoflong</a> </b> <b class="vimtag"> <a name="sizeoflong-variable">sizeoflong-variable</a> </b>
v:sizeoflong    一个 long 值的字节数。取决于 Vim 的编译环境。只对决定测试会否
                给出期待中的结果有用。

                                <b class="vimtag"> <a name="v:sizeofpointer">v:sizeofpointer</a> </b> <b class="vimtag"> <a name="sizeofpointer-variable">sizeofpointer-variable</a> </b>
v:sizeofpointer 一个 pointer 值的字节数。取决于 Vim 的编译环境。只对决定测试会
                否给出期待中的结果有用。

                                        <b class="vimtag"> <a name="v:statusmsg">v:statusmsg</a> </b> <b class="vimtag"> <a name="statusmsg-variable">statusmsg-variable</a> </b>
v:statusmsg     最近给出的状态消息。可以设置该变量。

                                        <b class="vimtag"> <a name="v:swapname">v:swapname</a> </b> <b class="vimtag"> <a name="swapname-variable">swapname-variable</a> </b>
v:swapname      只有在执行  <a href="autocmd.html#SwapExists">SwapExists</a>  自动命令时才合法: 找到的交换文件名。只
                读。

                                        <b class="vimtag"> <a name="v:swapchoice">v:swapchoice</a> </b> <b class="vimtag"> <a name="swapchoice-variable">swapchoice-variable</a> </b>
v:swapchoice     <a href="autocmd.html#SwapExists">SwapExists</a>  自动命令可以设置此值，以选择如何处理已有交换文件:
                        'o'     以只读方式打开
                        'e'     仍然编辑
                        'r'     恢复
                        'd'     删除交换文件
                        'q'     退出
                        'a'     中止
                该值应是单个字符的字符串。如果为空，用户会被询问，就像没有
                SwapExists 自动命令那样。缺省为空。

                                        <b class="vimtag"> <a name="v:swapcommand">v:swapcommand</a> </b> <b class="vimtag"> <a name="swapcommand-variable">swapcommand-variable</a> </b>
v:swapcommand   打开文件后执行的普通模式命令。可以用于  <a href="autocmd.html#SwapExists">SwapExists</a>  自动命令，
                用以让另一个 Vim 打开文件并跳转到合适的位置。例如，要跳转到某
                标签，用的值是 ":tag tagname\r"。":edit +cmd file" 用的值是
                ":cmd\r"。

                                <b class="vimtag"> <a name="v:t_TYPE">v:t_TYPE</a> </b> <b class="vimtag"> <a name="v:t_bool">v:t_bool</a> </b> <b class="vimtag"> <a name="t_bool-variable">t_bool-variable</a> </b>
v:t_bool         <a href="eval.html#Boolean">Boolean</a>  的类型值。只读。见:  <a href="builtin.html#type()">type()</a> 
                                        <b class="vimtag"> <a name="v:t_channel">v:t_channel</a> </b> <b class="vimtag"> <a name="t_channel-variable">t_channel-variable</a> </b>
v:t_channel      <a href="eval.html#Channel">Channel</a>  的类型值。只读。见:  <a href="builtin.html#type()">type()</a> 
                                        <b class="vimtag"> <a name="v:t_dict">v:t_dict</a> </b> <b class="vimtag"> <a name="t_dict-variable">t_dict-variable</a> </b>
v:t_dict         <a href="eval.html#Dictionary">Dictionary</a>  的类型值。只读。见:  <a href="builtin.html#type()">type()</a> 
                                        <b class="vimtag"> <a name="v:t_float">v:t_float</a> </b> <b class="vimtag"> <a name="t_float-variable">t_float-variable</a> </b>
v:t_float        <a href="eval.html#Float">Float</a>  的类型值。只读。见:  <a href="builtin.html#type()">type()</a> 
                                        <b class="vimtag"> <a name="v:t_func">v:t_func</a> </b> <b class="vimtag"> <a name="t_func-variable">t_func-variable</a> </b>
v:t_func         <a href="eval.html#Funcref">Funcref</a>  的类型值。只读。见:  <a href="builtin.html#type()">type()</a> 
                                        <b class="vimtag"> <a name="v:t_job">v:t_job</a> </b> <b class="vimtag"> <a name="t_job-variable">t_job-variable</a> </b>
v:t_job          <a href="eval.html#Job">Job</a>  的类型值。只读。见:  <a href="builtin.html#type()">type()</a> 
                                        <b class="vimtag"> <a name="v:t_list">v:t_list</a> </b> <b class="vimtag"> <a name="t_list-variable">t_list-variable</a> </b>
v:t_list         <a href="eval.html#List">List</a>  的类型值。只读。见:  <a href="builtin.html#type()">type()</a> 
                                        <b class="vimtag"> <a name="v:t_none">v:t_none</a> </b> <b class="vimtag"> <a name="t_none-variable">t_none-variable</a> </b>
v:t_none         <a href="eval.html#None">None</a>  的类型值。只读。见:  <a href="builtin.html#type()">type()</a> 
                                        <b class="vimtag"> <a name="v:t_number">v:t_number</a> </b> <b class="vimtag"> <a name="t_number-variable">t_number-variable</a> </b>
v:t_number       <a href="eval.html#Number">Number</a>  的类型值。只读。见:  <a href="builtin.html#type()">type()</a> 
                                        <b class="vimtag"> <a name="v:t_string">v:t_string</a> </b> <b class="vimtag"> <a name="t_string-variable">t_string-variable</a> </b>
v:t_string       <a href="eval.html#String">String</a>  的类型值。只读。见:  <a href="builtin.html#type()">type()</a> 
                                        <b class="vimtag"> <a name="v:t_blob">v:t_blob</a> </b> <b class="vimtag"> <a name="t_blob-variable">t_blob-variable</a> </b>
v:t_blob         <a href="eval.html#Blob">Blob</a>  的类型值。只读。见:  <a href="builtin.html#type()">type()</a> 
                                        <b class="vimtag"> <a name="v:t_class">v:t_class</a> </b> <b class="vimtag"> <a name="t_class-variable">t_class-variable</a> </b>
v:t_class        <a href="vim9class.html#class">class</a>  的类型值。只读。见:  <a href="builtin.html#type()">type()</a> 
                                        <b class="vimtag"> <a name="v:t_object">v:t_object</a> </b> <b class="vimtag"> <a name="t_object-variable">t_object-variable</a> </b>
v:t_object       <a href="vim9class.html#object">object</a>  的类型值。只读。见:  <a href="builtin.html#type()">type()</a> 

                                <b class="vimtag"> <a name="v:termresponse">v:termresponse</a> </b> <b class="vimtag"> <a name="termresponse-variable">termresponse-variable</a> </b>
v:termresponse  使用  <a href="term.html#t_RV">t_RV</a>  termcap 项目返回的终端的转义序列。Vim 收到 ESC [
                或者 CSI 开始，然后是 '&gt;' 或 '?'，并以一个 'c' 结束，并且其间
                只包含数字和 ';' 的转义序列的时候，会设置该值。
                如果设置该选项，会激活 TermResponse 自动命令事件，这样你就可以
                对终端的应答做出反应。可用  <a href="builtin.html#terminalprops()">terminalprops()</a>  来查看 Vim 对终端
                了解的情况。
                新的 xterm 的应答是: "<code class="special">&lt;Esc&gt;</code>[&gt; Pp ; Pv ; Pc c"。 Pp 是终端类型:
                0 代表 vt100，而 1 代表 vt220。 Pv 是补丁号 (因为这是 patch 95
                引入的，补丁号应该总是 95 或更高)。Pc 总是零。
                如果 Pv 为 141 或更高，Vim 会试图请求终端代码。只可用于 xterm
                 <a href="term.html#xterm-codes">xterm-codes</a> 。
                <code class="notvi">{仅当编译时加入  <a href="various.html#+termresponse">+termresponse</a>  特性才有效}</code>

                                                <b class="vimtag"> <a name="v:termblinkresp">v:termblinkresp</a> </b>
v:termblinkresp 终端用于  <a href="term.html#t_RC">t_RC</a>  termcap 项目的转义序列。用于找出终端光标是否闪
                烁。用于  <a href="terminal.html#term_getcursor()">term_getcursor()</a> 。

                                                <b class="vimtag"> <a name="v:termstyleresp">v:termstyleresp</a> </b>
v:termstyleresp 终端用于  <a href="term.html#t_RS">t_RS</a>  termcap 项目的转义序列。用于找出终端光标的形
                状。用于  <a href="terminal.html#term_getcursor()">term_getcursor()</a> 。

                                                <b class="vimtag"> <a name="v:termrbgresp">v:termrbgresp</a> </b>
v:termrbgresp   终端用于  <a href="term.html#t_RB">t_RB</a>  termcap 项目的转义序列。用于找出终端的背景色，
                见 <a href="options.html#'background'">'background'</a>。

                                                <b class="vimtag"> <a name="v:termrfgresp">v:termrfgresp</a> </b>
v:termrfgresp   终端用于  <a href="term.html#t_RF">t_RF</a>  termcap 项目的转义序列。用于找出终端的前景色。

                                                <b class="vimtag"> <a name="v:termu7resp">v:termu7resp</a> </b>
v:termu7resp    终端用于  <a href="term.html#t_u7">t_u7</a>  termcap 项目的转义序列。用于找出终端如何处理二
                义性宽度字符，见 <a href="options.html#'ambiwidth'">'ambiwidth'</a>。

                                        <b class="vimtag"> <a name="v:testing">v:testing</a> </b> <b class="vimtag"> <a name="testing-variable">testing-variable</a> </b>
v:testing       必须在  <a href="testing.html#test_garbagecollect_now()">test_garbagecollect_now()</a>  之前设置。
                另外，设置时，在 2 秒内不会显示特定的错误信息 (例如
                "<a href="options.html#'dictionary'">'dictionary'</a> option is empty")

                                <b class="vimtag"> <a name="v:this_session">v:this_session</a> </b> <b class="vimtag"> <a name="this_session-variable">this_session-variable</a> </b>
v:this_session  最近载入或者保存的会话文件的文件名  <a href="starting.html#:mksession">:mksession</a> 。可以设置该变
                量。如果没有保存过会话文件，该变量为空。
                为了后向兼容，这里也可以用 "this_session"，除非
                 <a href="eval.html#scriptversion">scriptversion</a>  为 3 或更高。

                                        <b class="vimtag"> <a name="v:throwpoint">v:throwpoint</a> </b> <b class="vimtag"> <a name="throwpoint-variable">throwpoint-variable</a> </b>
v:throwpoint    最近捕获且未完成的例外的抛出位置。输入的命令不会设置此变量。另
                见  <a href="eval.html#v:exception">v:exception</a>  和  <a href="eval.html#throw-variables">throw-variables</a> 。
                例如: 
<code class="example">        :try</code>
<code class="example">        :  throw "oops"</code>
<code class="example">        :catch /.*/</code>
<code class="example">        :  echo "Exception from" v:throwpoint</code>
<code class="example">        :endtry</code>
                输出: "Exception from test.vim, line 2"

                                        <b class="vimtag"> <a name="v:true">v:true</a> </b> <b class="vimtag"> <a name="true-variable">true-variable</a> </b>
v:true          取值为一的数值。用于在 JSON 里填入 "true"。见
                 <a href="builtin.html#json_encode()">json_encode()</a> 。
                用于字符串时会返回 "v:true"。 
<code class="example">                        echo v:true</code>
<code class="section">                        v:true </code>
                这样 eval() 可以把该字符串解析回相同的值。只读。
                 <a href="vim9.html#Vim9">Vim9</a>  脚本里可用布尔型的 "true" 值。

                                                <b class="vimtag"> <a name="v:val">v:val</a> </b> <b class="vimtag"> <a name="val-variable">val-variable</a> </b>
v:val            <a href="eval.html#List">List</a>  或  <a href="eval.html#Dictionary">Dictionary</a>  当前项目的值。只有在计算  <a href="builtin.html#map()">map()</a>  和
                 <a href="builtin.html#filter()">filter()</a>  里的表达式时才有效。只读。

                                        <b class="vimtag"> <a name="v:version">v:version</a> </b> <b class="vimtag"> <a name="version-variable">version-variable</a> </b>
v:version       Vim 的版本号: 主版本号乘以 100 加上副版本号。5.0 版本对应的是
                500。5.1 版本则是 501。只读。为了后向兼容，这里也可以用
                "version"，除非  <a href="eval.html#scriptversion">scriptversion</a>  为 3 或者更高。
                用  <a href="builtin.html#has()">has()</a>  可以检查是否包含某补丁，例如: 
<code class="example">                        if has("patch-7.4.123")</code>
                <code class="note">注意</code> 补丁号和版本有关，5.0 和 5.1 版本都有补丁号 123，但完全不
                同。

                                        <b class="vimtag"> <a name="v:versionlong">v:versionlong</a> </b> <b class="vimtag"> <a name="versionlong-variable">versionlong-variable</a> </b>
v:versionlong   类似于 v:version，但末四位数字包含补丁号。8.1 版本带补丁 123
                的值是 8010123。可以这样用: 
<code class="example">                        if v:versionlong &gt;= 8010123</code>
                不过，如果包含的补丁列表有空档这样不太完美。比如为了安全原因，
                有时旧的版本会打上新近的补丁。用 has() 函数可以确定是否包含某
                补丁。

                                <b class="vimtag"> <a name="v:vim_did_enter">v:vim_did_enter</a> </b> <b class="vimtag"> <a name="vim_did_enter-variable">vim_did_enter-variable</a> </b>
v:vim_did_enter 直到绝大部分的初始化工作做完之前保持为零。在  <a href="autocmd.html#VimEnter">VimEnter</a>  自动命
                令刚刚激活之前，设为一。

                                        <b class="vimtag"> <a name="v:warningmsg">v:warningmsg</a> </b> <b class="vimtag"> <a name="warningmsg-variable">warningmsg-variable</a> </b>
v:warningmsg    最近给出的<code class="note">警告</code>消息。该变量可以设置。

                                        <b class="vimtag"> <a name="v:windowid">v:windowid</a> </b> <b class="vimtag"> <a name="windowid-variable">windowid-variable</a> </b>
v:windowid      运行基于 X11 的任何 GUI，或者在终端运行且 Vim 连接到 X 服务器
                ( <a href="starting.html#-X">-X</a> ) 时，给出窗口号。
                运行 MS-Windows GUI 时，给出窗口的句柄。
                否则该值为零。
                <code class="note">注意</code>: Vim 内部的窗口请用  <a href="builtin.html#winnr()">winnr()</a>  或  <a href="builtin.html#win_getid()">win_getid()</a> ，见
                 <a href="windows.html#window-ID">window-ID</a> 。

</section><hr class="doubleline" /><section class=inner>
<h4>4. 内建函数                                             <b class="vimtag"> <a name="functions">functions</a> </b></h4>
 <a href="usr_41.html#function-list">function-list</a>  提供了按功能分组的一个函数列表。

所有内建函数和细节的按字母排序的列表现包含在一个单独的帮助文件里:
 <a href="builtin.html#builtin-functions">builtin-functions</a> 。

</section><hr class="doubleline" /><section class=inner>
<h4>5. 定义函数                                             <b class="vimtag"> <a name="user-functions">user-functions</a> </b></h4>
可以定义新的函数。调用的方式就像内建函数一样。函数接受参数，执行一系列 Ex 命
令，并返回值。

关于定义函数的大部分信息可见  <a href="userfunc.html#userfunc.txt">userfunc.txt</a> 。
关于执行快很多、支持类型检查还有更多优点的 Vim9 函数，参见  <a href="vim9.html#vim9.txt">vim9.txt</a> 。

</section><hr class="doubleline" /><section class=inner>
<h4>6. 花括号名字                                           <b class="vimtag"> <a name="curly-braces-names">curly-braces-names</a> </b></h4>
多数使用变量的地方可以改用 "花括号名字" 变量。和常规的变量名类似，但可以包含一
到多个花括号 <code class="special">{}</code> 包围的表达式，形如: 
<code class="example">        my_{adjective}_variable</code>
<code class="example"></code>
只可用于老式 Vim 脚本，不可用于  <a href="vim9.html#Vim9">Vim9</a>  脚本。

如果 Vim 遇到这种情形，它会计算花括号内的表达式，把结果放在表达式所在的位置，
然后重新解释整个字符串为完整的变量名。所以在上例中，如果变量 "adjective" 设为
"noisy"，那么引用的将是 "my_noisy_variable"。如果 "adjective" 设为 "quiet"，那
么引用的将是 "my_quiet_variable"。

一个这种形式的应用是建立一系列变量，由一个选项管理。比如，语句 
<code class="example">        echo my_{&amp;background}_message</code>
<code class="example"></code>
会显示 "my_dark_message" 或者 "my_light_message" 的内容，取决于 <a href="options.html#'background'">'background'</a>
的当前值。

你可以使用多个花括号对: 
<code class="example">        echo my_{adverb}_{adjective}_message</code>
..甚至嵌套使用: 
<code class="example">        echo my_{ad{end_of_word}}_message</code>
其中 "end_of_word" 可以是 "verb" 或者 "jective"。

不过，花括号里的表达式必须计算出合法的单个变量名，比如，这不行: 
<code class="example">        :let foo='a + b'</code>
<code class="example">        :echo c{foo}d</code>
.. 因为扩展的结果是 "ca + bd"，这不是合法的变量名。

                                                <b class="vimtag"> <a name="curly-braces-function-names">curly-braces-function-names</a> </b>
类似的，你可以调用和定义计算的出的函数名。比如: 
<code class="example">        :let func_end='whizz'</code>
<code class="example">        :call my_func_{func_end}(parameter)</code>
<code class="example"></code>
会调用函数 "my_func_whizz(parameter)"。

这样 <code class="emphasis">不</code> 行: 
<code class="example">  :let i = 3</code>
<code class="example">  :let @{i} = ''  " 报错</code>
<code class="example">  :echo @{i}      " 报错</code>
<code class="example"></code>
</section><hr class="doubleline" /><section class=inner>
<h4>7. 命令                                                 <b class="vimtag"> <a name="expression-commands">expression-commands</a> </b></h4>
<code class="note">备注</code>: Vim9 脚本中不使用  <a href="eval.html#:let">:let</a> 。 <a href="vim9.html#:var">:var</a>  用于变量声明而赋值不需命令。
 <a href="vim9.html#vim9-declaration">vim9-declaration</a> 

:let <code class="special">{var-name}</code> = <code class="special">{expr1}</code>                               <b class="vimtag"> <a name=":let">:let</a> </b> <b class="vimtag"> <a name="E18">E18</a> </b>
                        设置内部变量 <code class="special">{var-name}</code> 为表达式 <code class="special">{expr1}</code> 的计算结果。
                        该变量也会得到 <code class="special">{expr}</code> 的类型。如果 <code class="special">{var-name}</code> 不存在，
                        它会被创立。

:let <code class="special">{var-name}</code>[<code class="special">{idx}</code>] = <code class="special">{expr1}</code>                        <b class="vimtag"> <a name="E689">E689</a> </b> <b class="vimtag"> <a name="E1141">E1141</a> </b>
                        设置列表项目为表达式 <code class="special">{expr1}</code> 的返回值。<code class="special">{var-name}</code> 必须
                        引用列表而 <code class="special">{idx}</code> 必须是该列表里合法的索引值。嵌套的列
                        表可以重复使用索引。
                        不能用于给列表  <a href="eval.html#List">List</a>  增加项目。
                        不能用来给字符串改变个别字节。为此你可以这么做: 
<code class="example">                                :let var = var[0:2] .. 'X' .. var[4:]</code>
                        如果 <code class="special">{var-name}</code> 是  <a href="eval.html#Blob">Blob</a> ，<code class="special">{idx}</code> 可以等于 blob 的长
                        度，此时附加一个字节。

                                        <b class="vimtag"> <a name="E711">E711</a> </b> <b class="vimtag"> <a name="E719">E719</a> </b> <b class="vimtag"> <a name="E1165">E1165</a> </b> <b class="vimtag"> <a name="E1166">E1166</a> </b> <b class="vimtag"> <a name="E1183">E1183</a> </b>
:let <code class="special">{var-name}</code>[<code class="special">{idx1}</code>:<code class="special">{idx2}</code>] = <code class="special">{expr1}</code>                <b class="vimtag"> <a name="E708">E708</a> </b> <b class="vimtag"> <a name="E709">E709</a> </b> <b class="vimtag"> <a name="E710">E710</a> </b>
                        设置  <a href="eval.html#List">List</a>  的一系列项目为表达式 <code class="special">{expr1}</code> 的返回值，后
                        者必须是正确数量项目的列表。
                        <code class="special">{idx1}</code> 可以省略，这时以零代替。
                        <code class="special">{idx2}</code> 可以省略，这时意味着到列表尾部。
                        如果选择的项目范围部分越过列表的尾部，会加入新的项目。

                        <b class="vimtag"> <a name=":let+%20">:let+=</a> </b> <b class="vimtag"> <a name=":let-%20">:let-=</a> </b> <b class="vimtag"> <a name=":letstar%20">:letstar=</a> </b> <b class="vimtag"> <a name=":let%2F%20">:let/=</a> </b>  <b class="vimtag"> <a name=":let%%20">:let%=</a> </b>
                        <b class="vimtag"> <a name=":let.%20">:let.=</a> </b> <b class="vimtag"> <a name=":let..%20">:let..=</a> </b> <b class="vimtag"> <a name="E734">E734</a> </b> <b class="vimtag"> <a name="E985">E985</a> </b> <b class="vimtag"> <a name="E1019">E1019</a> </b>
:let <code class="special">{var}</code> += <code class="special">{expr1}</code>   类似于 ":let <code class="special">{var}</code> = <code class="special">{var}</code> + <code class="special">{expr1}</code>"。
:let <code class="special">{var}</code> -= <code class="special">{expr1}</code>   类似于 ":let <code class="special">{var}</code> = <code class="special">{var}</code> - <code class="special">{expr1}</code>"。
:let <code class="special">{var}</code> *= <code class="special">{expr1}</code>   类似于 ":let <code class="special">{var}</code> = <code class="special">{var}</code> * <code class="special">{expr1}</code>"。
:let <code class="special">{var}</code> /= <code class="special">{expr1}</code>   类似于 ":let <code class="special">{var}</code> = <code class="special">{var}</code> / <code class="special">{expr1}</code>"。
:let <code class="special">{var}</code> %= <code class="special">{expr1}</code>   类似于 ":let <code class="special">{var}</code> = <code class="special">{var}</code> % <code class="special">{expr1}</code>"。
:let <code class="special">{var}</code> .= <code class="special">{expr1}</code>   类似于 ":let <code class="special">{var}</code> = <code class="special">{var}</code> . <code class="special">{expr1}</code>"。
:let <code class="special">{var}</code> ..= <code class="special">{expr1}</code>  类似于 ":let <code class="special">{var}</code> = <code class="special">{var}</code> .. <code class="special">{expr1}</code>"。
                        如果 <code class="special">{var}</code> 还没有设置或者 <code class="special">{var}</code> 和 <code class="special">{expr1}</code> 的类型不符
                        合操作符的要求，失败。
                        Vim 脚本版本 2 或之后不支持  <code class="badlink">.=</code>  ，见
                         <a href="eval.html#vimscript-version">vimscript-version</a> 。


:let $<code class="special">{env-name}</code> = <code class="special">{expr1}</code>                      <b class="vimtag"> <a name=":let-environment">:let-environment</a> </b> <b class="vimtag"> <a name=":let-$">:let-$</a> </b>
                        设置环境变量 <code class="special">{env-name}</code> 为表达式 <code class="special">{expr1}</code> 的计算结果。
                        它总是字符串型。

                        在有的系统中使环境变量为空会把它删除。很多系统不区别不
                        置位的环境变量和空的环境变量。

:let $<code class="special">{env-name}</code> .= <code class="special">{expr1}</code>
                        把 <code class="special">{expr1}</code> 附加到环境变量 <code class="special">{env-name}</code> 之后。如果该环境
                        变量还不存在，相当于 "="。

:let @<code class="special">{reg-name}</code> = <code class="special">{expr1}</code>                      <b class="vimtag"> <a name=":let-register">:let-register</a> </b> <b class="vimtag"> <a name=":let-@">:let-@</a> </b>
                        把表达式 <code class="special">{expr1}</code> 的计算结果写到寄存器 <code class="special">{reg-name}</code> 里。
                        <code class="special">{reg-name}</code> 必须是单个字符，而且是一个可以写入的寄存器
                        (见  <a href="change.html#registers">registers</a> )。"@@" 可以用来访问无名寄存器，而 "@/"
                        设置搜索模式。
                        如果 <code class="special">{expr1}</code> 的结果以 <code class="special">&lt;CR&gt;</code> 或 <code class="special">&lt;NL&gt;</code> 结束，该寄存器会成
                        为面向行类型，不然，它会成为面向字符类型。
                        这可以用来清除最近的搜索模式: 
<code class="example">                                :let @/ = ""</code>
                        这和搜索空字符串不同，后者会在任何地方得到匹配。

:let @<code class="special">{reg-name}</code> .= <code class="special">{expr1}</code>
                        把 <code class="special">{expr1}</code> 附加到寄存器 <code class="special">{reg-name}</code> 之后。如果寄存器为
                        空，相当于把它设为 <code class="special">{expr1}</code> 的值。

:let &amp;<code class="special">{option-name}</code> = <code class="special">{expr1}</code>                   <b class="vimtag"> <a name=":let-option">:let-option</a> </b> <b class="vimtag"> <a name=":let-&">:let-&amp;</a> </b>
                        设置选项 <code class="special">{option-name}</code> 为表达式 <code class="special">{expr1}</code> 的计算结果。字
                        符串或数值类型的值总会被转化为选项需要的类型。
                        对于局部于窗口或者缓冲区的选项而言，这和  <a href="options.html#:set">:set</a>  命令的
                        效果相同: 局部值和全局值都被改变。
                        例如: 
<code class="example">                                :let &amp;path = &amp;path .. ',/usr/local/include'</code>
                        也可用于形如 t_xx 的终端代码。但只可用字母数字形式的名
                        字。例如: 
<code class="example">                                :let &amp;t_k1 = "\&lt;Esc&gt;[234;"</code>
                        如果代码还不存在，会新建一个终端键值，因此不会报错。

:let &amp;<code class="special">{option-name}</code> .= <code class="special">{expr1}</code>
                        对字符串选项: 附加 <code class="special">{expr1}</code> 到选项值之后。和  <a href="options.html#:set+%20">:set+=</a> 
                        不同，不会插入逗号。

:let &amp;<code class="special">{option-name}</code> += <code class="special">{expr1}</code>
:let &amp;<code class="special">{option-name}</code> -= <code class="special">{expr1}</code>
                        对数值或布尔选项: 加减 <code class="special">{expr1}</code>。

:let &amp;l:<code class="special">{option-name}</code> = <code class="special">{expr1}</code>
:let &amp;l:<code class="special">{option-name}</code> .= <code class="special">{expr1}</code>
:let &amp;l:<code class="special">{option-name}</code> += <code class="special">{expr1}</code>
:let &amp;l:<code class="special">{option-name}</code> -= <code class="special">{expr1}</code>
                        同上，但只设置选项的局部值 (如果有的话)。和
                         <a href="options.html#:setlocal">:setlocal</a>  类似。

:let &amp;g:<code class="special">{option-name}</code> = <code class="special">{expr1}</code>
:let &amp;g:<code class="special">{option-name}</code> .= <code class="special">{expr1}</code>
:let &amp;g:<code class="special">{option-name}</code> += <code class="special">{expr1}</code>
:let &amp;g:<code class="special">{option-name}</code> -= <code class="special">{expr1}</code>
                        同上，但只设置选项的全局值 (如果有的话)。和
                         <a href="options.html#:setglobal">:setglobal</a>  类似。

                                                                <b class="vimtag"> <a name="E1093">E1093</a> </b>
:let [<code class="special">{name1}</code>, <code class="special">{name2}</code>, ...] = <code class="special">{expr1}</code>          <b class="vimtag"> <a name=":let-unpack">:let-unpack</a> </b> <b class="vimtag"> <a name="E687">E687</a> </b> <b class="vimtag"> <a name="E688">E688</a> </b>
                        <code class="special">{expr1}</code> 计算结果必须是  <a href="eval.html#List">List</a> 。该列表的第一项赋给
                        <code class="special">{name1}</code>，第二项给 <code class="special">{name2}</code>，依此类推。
                        命名的数量必须匹配  <a href="eval.html#List">List</a>  项目的数量。
                        每个名字必须是上面提到的 ":let" 命令的项目之一。
                        例如: 
<code class="example">                                :let [s, item] = GetItem(s)</code>
                        细节: 先计算 <code class="special">{expr1}</code>，然后按顺序依次进行赋值。如果
                        <code class="special">{name2}</code> 依赖于 <code class="special">{name1}</code>，该细节就有关系。例如: 
<code class="example">                                :let x = [0, 1]</code>
<code class="example">                                :let i = 0</code>
<code class="example">                                :let [i, x[i]] = [1, 2]</code>
<code class="example">                                :echo x</code>
                        结果是 [0, 2]。

:let [<code class="special">{name1}</code>, <code class="special">{name2}</code>, ...] .= <code class="special">{expr1}</code>
:let [<code class="special">{name1}</code>, <code class="special">{name2}</code>, ...] += <code class="special">{expr1}</code>
:let [<code class="special">{name1}</code>, <code class="special">{name2}</code>, ...] -= <code class="special">{expr1}</code>
                        同上，但附加/加/减值到每个  <a href="eval.html#List">List</a>  项目。

:let [<code class="special">{name}</code>, ..., ; <code class="special">{lastname}</code>] = <code class="special">{expr1}</code>                              <b class="vimtag"> <a name="E452">E452</a> </b>
                        类似于上面的  <a href="eval.html#:let-unpack">:let-unpack</a> ，但  <a href="eval.html#List">List</a>  可以包含比给出名
                        字的数量更多的项目。列表其余项目赋给 <code class="special">{lastname}</code>。
                        如果没有余下的项目，<code class="special">{lastname}</code> 设为空列表。
                        例如: 
<code class="example">                                :let [a, b; rest] = ["aval", "bval", 3, 4]</code>

:let [<code class="special">{name}</code>, ..., ; <code class="special">{lastname}</code>] .= <code class="special">{expr1}</code>
:let [<code class="special">{name}</code>, ..., ; <code class="special">{lastname}</code>] += <code class="special">{expr1}</code>
:let [<code class="special">{name}</code>, ..., ; <code class="special">{lastname}</code>] -= <code class="special">{expr1}</code>
                        同上，但附加/加/减值到每个  <a href="eval.html#List">List</a>  项目。

                                                <b class="vimtag"> <a name=":let%20%3C%3C">:let=&lt;&lt;</a> </b> <b class="vimtag"> <a name=":let-heredoc">:let-heredoc</a> </b>
                                        <b class="vimtag"> <a name="E990">E990</a> </b> <b class="vimtag"> <a name="E991">E991</a> </b> <b class="vimtag"> <a name="E172">E172</a> </b> <b class="vimtag"> <a name="E221">E221</a> </b> <b class="vimtag"> <a name="E1145">E1145</a> </b>
:let <code class="special">{var-name}</code> =&lt;&lt; <code class="special">[trim]</code> <code class="special">[eval]</code> <code class="special">{endmarker}</code>
text...
text...
<code class="special">{endmarker}</code>
                        设置内部变量 <code class="special">{var-name}</code> 为由 <code class="special">{endmarker}</code> 字符串定界的
                        文本行的  <a href="eval.html#List">List</a> 。文本行视作  <a href="eval.html#literal-string">literal-string</a> 。

                        不给出 "eval" 时，每个文本行视作  <a href="eval.html#literal-string">literal-string</a> ，但
                        单引用不需要加倍。
                        给出 "eval" 时，计算形如 <code class="special">{expr}</code> 的 Vim 表达式，并用返
                        回结果来替代该表达式，如用  <a href="eval.html#interpolated-string">interpolated-string</a>  一
                        样。
                        扩展 $HOME 的例子: 
<code class="example">                                let lines =&lt;&lt; trim eval END</code>
<code class="example">                                  some text</code>
<code class="example">                                  See the file {$HOME}/.vimrc</code>
<code class="example">                                  more text</code>
<code class="example">                                END</code>
                        一行里可有多个 Vim 表达式，但一个表达式不能跨越多行。
                        如果表达式计算失败，赋值本身失败。

                        <code class="special">{endmarker}</code> 不能包含空白。
                        <code class="special">{endmarker}</code> 不能以小写字母开头。
                        末行必须以 <code class="special">{endmarker}</code> 字符串结束，而不能有其它字符。
                        小心 <code class="special">{endmarker}</code> 之后的空白！

                        如果不给出 "trim" 保留文本行中的空白字符。如果
                        <code class="special">{endmarker}</code> 之前给出 "trim"，则删除缩进，所以可以这
                        样: 
<code class="example">                                let text =&lt;&lt; trim END</code>
<code class="example">                                   if ok</code>
<code class="example">                                     echo 'done'</code>
<code class="example">                                   endif</code>
<code class="example">                                END</code>
                        结果是: ["if ok", "  echo <code class="badlink">'done'</code>", "endif"]
                        marker 必须和 "let" 对齐，此时从所有文本行中删除首行的
                        缩进。
                        具体地说: 和首个非空文本行引导缩进完全一致的所有输入行
                        的缩引导进会被删除。
                        和  <code class="badlink">let</code>  之前的引导缩进完全一致的包含 <code class="special">{endmarker}</code> 的行
                        的所有的引导缩进也会被删除。
                        <code class="note">注意</code> 这里空格和制表是有区别的。

                        如果 <code class="special">{var-name}</code> 还不存在，会被创建。
                        不能跟在其它命令后面，但后面可以跟注释。

                        要避免续行符的使用，考虑在 <a href="options.html#'cpoptions'">'cpoptions'</a> 中加入 'C': 
<code class="example">                                set cpo+=C</code>
<code class="example">                                let var =&lt;&lt; END</code>
<code class="example">                                   \ leading backslash</code>
<code class="example">                                END</code>
<code class="example">                                set cpo-=C</code>

                        示例: 
<code class="example">                                let var1 =&lt;&lt; END</code>
<code class="example">                                Sample text 1</code>
<code class="example">                                    Sample text 2</code>
<code class="example">                                Sample text 3</code>
<code class="example">                                END</code>
<code class="example"></code>
<code class="example">                                let data =&lt;&lt; trim DATA</code>
<code class="example">                                        1 2 3 4</code>
<code class="example">                                        5 6 7 8</code>
<code class="example">                                DATA</code>
<code class="example"></code>
<code class="example">                                let code =&lt;&lt; trim eval CODE</code>
<code class="example">                                   let v = {10 + 20}</code>
<code class="example">                                   let h = "{$HOME}"</code>
<code class="example">                                   let s = "{Str1()} abc {Str2()}"</code>
<code class="example">                                   let n = {MyFunc(3, 4)}</code>
<code class="example">                                CODE</code>

                                                                <b class="vimtag"> <a name="E121">E121</a> </b>
:let <code class="special">{var-name}</code> ..      列出变量 <code class="special">{var-name}</code> 的值。可以给出多个变量的名字。这里
                        识别特殊的名字包括:             <b class="vimtag"> <a name="E738">E738</a> </b>
                          g:    全局变量
                          b:    缓冲区的局部变量
                          w:    窗口的局部变量
                          t:    标签页的局部变量
                          s:    脚本的局部变量
                          l:    函数的局部变量
                          v:    Vim 变量。
                        不适用于 Vim9 脚本。 <a href="vim9.html#vim9-declaration">vim9-declaration</a> 

:let                    列出所有变量的值。变量的类型在值之前给出:
                               &lt;空&gt;     字符串
                                #       数值
                                *       函数引用
                        不适用于 Vim9 脚本。 <a href="vim9.html#vim9-declaration">vim9-declaration</a> 


:unl[et][!] <code class="special">{name}</code> ...                  <b class="vimtag"> <a name=":unlet">:unlet</a> </b> <b class="vimtag"> <a name=":unl">:unl</a> </b> <b class="vimtag"> <a name="E108">E108</a> </b> <b class="vimtag"> <a name="E795">E795</a> </b> <b class="vimtag"> <a name="E1081">E1081</a> </b>
                        删除内部变量 <code class="special">{var-name}</code>。可以给出多个变量的名字。它们
                        都被删除。该名字也可以是  <a href="eval.html#List">List</a>  或  <a href="eval.html#Dictionary">Dictionary</a>  项目。
                        如果使用 [!]，即使变量不存在也不会给出错误。
                         <a href="eval.html#List">List</a>  里可以删除一到多个项目: 
<code class="example">                                :unlet list[3]    " remove fourth item</code>
<code class="example">                                :unlet list[3:]   " remove fourth item to last</code>
                         <a href="eval.html#Dictionary">Dictionary</a>  里一次只能删除一个项目: 
<code class="example">                                :unlet dict['two']</code>
<code class="example">                                :unlet dict.two</code>
                        这对于清除全局和脚本局部变量很有用 (脚本结束时并不自动
                        删除这些变量)。函数局部变量在函数结束时是自动清除的。
                         <a href="vim9.html#Vim9">Vim9</a>  脚本不能删除函数或脚本内声明的变量。

:unl[et] $<code class="special">{env-name}</code> ...                        <b class="vimtag"> <a name=":unlet-environment">:unlet-environment</a> </b> <b class="vimtag"> <a name=":unlet-$">:unlet-$</a> </b>
                        删除环境变量 <code class="special">{env-name}</code>。
                        在一个 :unlet 命令里可以混合 <code class="special">{name}</code> 和 $<code class="special">{env-name}</code>。
                        不对不存在的变量报错，即使没有 ! 也是如此。
                        如果系统不支持删除环境变量，则将它清空。

                                                <b class="vimtag"> <a name=":cons">:cons</a> </b> <b class="vimtag"> <a name=":const">:const</a> </b> <b class="vimtag"> <a name="E1018">E1018</a> </b>
:cons[t] <code class="special">{var-name}</code> = <code class="special">{expr1}</code>
:cons[t] [<code class="special">{name1}</code>, <code class="special">{name2}</code>, ...] = <code class="special">{expr1}</code>
:cons[t] [<code class="special">{name}</code>, ..., ; <code class="special">{lastname}</code>] = <code class="special">{expr1}</code>
:cons[t] <code class="special">{var-name}</code> =&lt;&lt; <code class="special">[trim]</code> <code class="special">{marker}</code>
text...
text...
<code class="special">{marker}</code>
                        和  <a href="eval.html#:let">:let</a>  类似，但设置值后额外地给变量加锁。等价于
                         <a href="eval.html#:let">:let</a>  之后立即用  <a href="eval.html#:lockvar">:lockvar</a>  给变量加锁，所以: 
<code class="example">                                :const x = 1</code>
                        等价于: 
<code class="example">                                :let x = 1</code>
<code class="example">                                :lockvar! x</code>
                        <code class="note">注意</code>: Vim9 脚本中  <a href="eval.html#:const">:const</a>  的工作方式不同，可见
                         <a href="vim9.html#vim9-const">vim9-const</a> 
                        可用于保证变量之后不会被修改。如果值为列表或字典常量，
                        其中的项目也不能被修改: 
<code class="example">                                const ll = [1, 2, 3]</code>
<code class="example">                                let ll[1] = 5  " 报错！</code>
                        嵌套引用不加锁: 
<code class="example">                                let lvar = ['a']</code>
<code class="example">                                const lconst = [0, lvar]</code>
<code class="example">                                let lconst[0] = 2  " 报错！</code>
<code class="example">                                let lconst[1][0] = 'b'  " OK</code>
                                                        <b class="vimtag"> <a name="E995">E995</a> </b>
                         <a href="eval.html#:const">:const</a>  不能用来修改变量: 
<code class="example">                                :let x = 1</code>
<code class="example">                                :const x = 2  " Error!</code>
                                                        <b class="vimtag"> <a name="E996">E996</a> </b>
                        <code class="note">注意</code> 这里不能使用环境变量、选项值和寄存器值，因为它们
                        不能被锁定。

:cons[t]
:cons[t] <code class="special">{var-name}</code>
                        如果不给出参数或只给出 <code class="special">{var-name}</code>，等价于  <a href="eval.html#:let">:let</a> 。

:lockv[ar][!] <code class="special">[depth]</code> <code class="special">{name}</code> ...                        <b class="vimtag"> <a name=":lockvar">:lockvar</a> </b> <b class="vimtag"> <a name=":lockv">:lockv</a> </b>
                        给内部变量 <code class="special">{name}</code> 加锁。加锁意味着不能再修改该变量 (直
                        到它被解锁为止)。
                        加锁的变量可以删除: 
<code class="example">                                :lockvar v</code>
<code class="example">                                :let v = 'asdf'   " 失败！</code>
<code class="example">                                :unlet v          " 没问题</code>
                        <b class="vimtag"> <a name="E741">E741</a> </b> <b class="vimtag"> <a name="E940">E940</a> </b> <b class="vimtag"> <a name="E1118">E1118</a> </b> <b class="vimtag"> <a name="E1119">E1119</a> </b> <b class="vimtag"> <a name="E1120">E1120</a> </b> <b class="vimtag"> <a name="E1121">E1121</a> </b> <b class="vimtag"> <a name="E1122">E1122</a> </b>
                        如果试图修改加锁的变量，你会得到错误信息: "E741: Value
                        is locked: <code class="special">{name}</code>"。
                        如果试图加锁或解锁内建变量，会报错: "E940: Cannot lock
                        or unlock variable <code class="special">{name}</code>"。


                        给  <a href="eval.html#List">List</a>  或  <a href="eval.html#Dictionary">Dictionary</a>  加锁时用到 <code class="special">[depth]</code>。它决定加
                        锁到达的深度:
                                0       给变量 <code class="special">{name}</code> 加锁，但其值可修改。
                                1       给  <a href="eval.html#List">List</a>  或  <a href="eval.html#Dictionary">Dictionary</a>  自身加锁。不
                                        能增加或者删除项目，但你可以修改它们的
                                        值。
                                2       给这些值也加锁，不能修改项目。如果项目
                                        是  <a href="eval.html#List">List</a>  或  <a href="eval.html#Dictionary">Dictionary</a> ，不能增加或
                                        删除其中项目，但仍然可以修改项目值。
                                3       同 2，但又适用于  <a href="eval.html#List">List</a>  /  <a href="eval.html#Dictionary">Dictionary</a> 
                                        中的  <a href="eval.html#List">List</a>  /  <a href="eval.html#Dictionary">Dictionary</a>  项目，更深
                                        一层。
                        缺省的 <code class="special">[depth]</code> 为 2，<code class="special">{name}</code> 是  <a href="eval.html#List">List</a>  或  <a href="eval.html#Dictionary">Dictionary</a> 
                        时，不能修改项目值。

                        <code class="special">[depth]</code> 为 0 的示例: 
<code class="example">                                let mylist = [1, 2, 3]</code>
<code class="example">                                lockvar 0 mylist</code>
<code class="example">                                let mylist[0] = 77      " OK</code>
<code class="example">                                call add(mylist, 4]     " OK</code>
<code class="example">                                let mylist = [7, 8, 9]  " 出错！</code>
                                                                <b class="vimtag"> <a name="E743">E743</a> </b>
                        要使用没有限制的深度，用 [!] 并省略 <code class="special">[depth]</code>。不过，为
                        了捕获循环，设定最大深度为 100。

                        <code class="note">注意</code> 如果两个变量引用同一个  <a href="eval.html#List">List</a>  而你锁住其中一个，
                        通过另一个变量来访问  <a href="eval.html#List">List</a>  也同时被锁住。
                        例如: 
<code class="example">                                :let l = [0, 1, 2, 3]</code>
<code class="example">                                :let cl = l</code>
<code class="example">                                :lockvar l</code>
<code class="example">                                :let cl[1] = 99         " won't work!</code>
                        为了避免这一点，可以给列表建立备份。见  <a href="builtin.html#deepcopy()">deepcopy()</a> 。


:unlo[ckvar][!] <code class="special">[depth]</code> <code class="special">{name}</code> ...              <b class="vimtag"> <a name=":unlockvar">:unlockvar</a> </b> <b class="vimtag"> <a name=":unlo">:unlo</a> </b> <b class="vimtag"> <a name="E1246">E1246</a> </b>
                        给内部变量 <code class="special">{name}</code> 解锁。和  <a href="eval.html#:lockvar">:lockvar</a>  刚好相反。

                        如果 <code class="special">{name}</code> 不存在:
                        -  <a href="vim9.html#Vim9">Vim9</a>  脚本会报错。
                        - 老式脚本会安静地忽略。

:if <code class="special">{expr1}</code>                     <b class="vimtag"> <a name=":if">:if</a> </b> <b class="vimtag"> <a name=":end">:end</a> </b> <b class="vimtag"> <a name=":endif">:endif</a> </b> <b class="vimtag"> <a name=":en">:en</a> </b> <b class="vimtag"> <a name="E171">E171</a> </b> <b class="vimtag"> <a name="E579">E579</a> </b> <b class="vimtag"> <a name="E580">E580</a> </b>
:en[dif]                如果 <code class="special">{expr}</code> 计算为非零，执行命令直到其后匹配的  <a href="eval.html#:else">:else</a> 
                        或者  <a href="eval.html#:endif">:endif</a>  为止。
                        虽然短形式可用，建议使用  <a href="eval.html#:endif">:endif</a>  全名以避免混淆，并使
                        自动缩进能正确工作。

                        从 Vim 版本 4.5 到 5.0， <a href="eval.html#:if">:if</a>  和  <a href="eval.html#:endif">:endif</a>  之间的 Ex 命
                        令被忽略。提供这两个命令只是为了后向兼容 (<code class="vim">译者注</code>，原文
                        如此)，以方便未来的扩展。可以嵌套。<code class="note">注意</code> 任何的  <a href="eval.html#:else">:else</a> 
                        或  <a href="eval.html#:elseif">:elseif</a>  也被忽略， <code class="badlink">else</code>  部分也一样不会执行。

                        利用这一点，你可以保持和旧版本的兼容: 
<code class="example">                                :if version &gt;= 500</code>
<code class="example">                                :  版本 5 专用的命令</code>
<code class="example">                                :endif</code>
                        为了找到  <code class="badlink">endif</code> ，仍然需要分析命令。有时，旧版本的 Vim
                        不能识别新的命令。比如， <a href="various.html#:silent">:silent</a>  被识别为
                         <a href="change.html#:substitute">:substitute</a>  命令。这种情形可以用  <a href="eval.html#:execute">:execute</a>  来避
                        免: 
<code class="example">                                :if version &gt;= 600</code>
<code class="example">                                :  execute "silent 1,$delete"</code>
<code class="example">                                :endif</code>

                         <a href="vim9.html#Vim9">Vim9</a>  脚本里  <a href="eval.html#:endif">:endif</a>  不能用短形式，以提高脚本的可读
                        性。
                        <code class="note">注意</code>:  <a href="insert.html#:append">:append</a>  和  <a href="insert.html#:insert">:insert</a>  命令在  <a href="eval.html#:if">:if</a>  和  <a href="eval.html#:endif">:endif</a> 
                        之间不能正常工作。

                                                <b class="vimtag"> <a name=":else">:else</a> </b> <b class="vimtag"> <a name=":el">:el</a> </b> <b class="vimtag"> <a name="E581">E581</a> </b> <b class="vimtag"> <a name="E583">E583</a> </b>
:el[se]                 如果这之前的命令没有被执行，执行命令直到其后匹配的
                         <a href="eval.html#:else">:else</a>  或  <a href="eval.html#:endif">:endif</a> 。
                         <a href="vim9.html#Vim9">Vim9</a>  脚本里  <a href="eval.html#:else">:else</a>  不能用短形式，以提高脚本的可读
                        性。

                                        <b class="vimtag"> <a name=":elseif">:elseif</a> </b> <b class="vimtag"> <a name=":elsei">:elsei</a> </b> <b class="vimtag"> <a name="E582">E582</a> </b> <b class="vimtag"> <a name="E584">E584</a> </b>
:elsei[f] <code class="special">{expr1}</code>        <a href="eval.html#:else">:else</a>   <a href="eval.html#:if">:if</a>  的缩写，而且无需另一个  <a href="eval.html#:endif">:endif</a> 。
                         <a href="vim9.html#Vim9">Vim9</a>  脚本里  <a href="eval.html#:elseif">:elseif</a>  不能用短形式，以提高脚本的可读
                        性。

:wh[ile] <code class="special">{expr1}</code>                        <b class="vimtag"> <a name=":while">:while</a> </b> <b class="vimtag"> <a name=":endwhile">:endwhile</a> </b> <b class="vimtag"> <a name=":wh">:wh</a> </b> <b class="vimtag"> <a name=":endw">:endw</a> </b>
                                                <b class="vimtag"> <a name="E170">E170</a> </b> <b class="vimtag"> <a name="E585">E585</a> </b> <b class="vimtag"> <a name="E588">E588</a> </b> <b class="vimtag"> <a name="E733">E733</a> </b>
:endw[hile]             只要 <code class="special">{expr1}</code> 计算的结果非零，重复  <a href="eval.html#:while">:while</a>  和
                         <a href="eval.html#:endwhile">:endwhile</a>  之间的命令。
                        如果发现循环里有命令出错，从  <code class="badlink">endwhile</code>  之后继续执行。
                        例如: 
<code class="example">                                :let lnum = 1</code>
<code class="example">                                :while lnum &lt;= line("$")</code>
<code class="example">                                   :call FixLine(lnum)</code>
<code class="example">                                   :let lnum = lnum + 1</code>
<code class="example">                                :endwhile</code>

                         <a href="vim9.html#Vim9">Vim9</a>  脚本里  <a href="eval.html#:while">:while</a>  和  <code class="badlink">:endwhite</code>  不能用短形式，以
                        提高脚本的可读性。
                        <code class="note">注意</code>:  <a href="insert.html#:append">:append</a>  和  <a href="insert.html#:insert">:insert</a>  命令在  <a href="eval.html#:while">:while</a>  和  <a href="eval.html#:for">:for</a> 
                        循环里不能正常工作。

:for <code class="special">{var}</code> in <code class="special">{object}</code>                                  <b class="vimtag"> <a name=":for">:for</a> </b> <b class="vimtag"> <a name="E690">E690</a> </b> <b class="vimtag"> <a name="E732">E732</a> </b>
:endfo[r]                                               <b class="vimtag"> <a name=":endfo">:endfo</a> </b> <b class="vimtag"> <a name=":endfor">:endfor</a> </b>
                        为每个 <code class="special">{object}</code> 项目重复执行  <a href="eval.html#:for">:for</a>  和  <a href="eval.html#:endfor">:endfor</a>  之间
                        的命令。<code class="special">{object}</code> 可以是  <a href="eval.html#List">List</a> 、 <a href="eval.html#Blob">Blob</a>  或  <a href="eval.html#String">String</a> 。
                        <b class="vimtag"> <a name="E1177">E1177</a> </b>

                        变量 <code class="special">{var}</code> 设为每个项目的值。 <a href="vim9.html#Vim9">Vim9</a>  脚本里循环变量不能
                        事先声明过，除非是全局/窗口/标签页/缓冲区变量。

                        如果循环里某个命令出错，从  <code class="badlink">endfor</code>  之后继续执行。
                        在循环里修改 <code class="special">{object}</code> 影响使用的项目。如果不希望如此，
                        构建一个备份: 
<code class="example">                                :for item in copy(mylist)</code>

                        如果 <code class="special">{object}</code> 为  <a href="eval.html#List">List</a>  且没有备份，老式脚本里 Vim 在
                        为当前项目执行命令前保存列表里下一个项目的引用。这样，
                        删除当前项目不会影响循环的继续。而删除任何后来的项目也
                        会使循环跳过它。这意味着下例可以工作 (一个效率低下的清
                        空列表的方法): 
<code class="example">                                for item in mylist</code>
<code class="example">                                   call remove(mylist, 0)</code>
<code class="example">                                endfor</code>
                        <code class="note">注意</code> 给  <a href="eval.html#List">List</a>  调整顺序 (例如用 sort() 或 reverse())
                        可能会有意想不到的效果。
                         <a href="vim9.html#Vim9">Vim9</a>  脚本使用索引。如果当前项目之前的一个项目被删
                        除，跳过下个项目。

                        如果 <code class="special">{object}</code> 为  <a href="eval.html#Blob">Blob</a> ，Vim 总是先建立备份再循环。和
                         <a href="eval.html#List">List</a>  不同，对  <a href="eval.html#Blob">Blob</a>  的修改不影响循环。

                        如果 <code class="special">{object}</code> 为  <a href="eval.html#String">String</a> ，每个项目是带单个字符加上可
                        能的组合字符的字符串。

                         <a href="vim9.html#Vim9">Vim9</a>  脚本里  <a href="eval.html#:endfor">:endfor</a>  不能用短形式，以提高脚本的可读
                        性。

:for [<code class="special">{var1}</code>, <code class="special">{var2}</code>, ...] in <code class="special">{listlist}</code>
:endfo[r]                                                       <b class="vimtag"> <a name="E1140">E1140</a> </b>
                        和上面  <a href="eval.html#:for">:for</a>  类似，但每个 <code class="special">{listlist}</code> 项目必须是列表，
                        其中每个项目被依次赋予 <code class="special">{var1}</code>、<code class="special">{var2}</code> 等。例如: 
<code class="example">                                :for [lnum, col] in [[1, 3], [2, 5], [3, 8]]</code>
<code class="example">                                   :echo getline(lnum)[col]</code>
<code class="example">                                :endfor</code>

                                                <b class="vimtag"> <a name=":continue">:continue</a> </b> <b class="vimtag"> <a name=":con">:con</a> </b> <b class="vimtag"> <a name="E586">E586</a> </b>
:con[tinue]             在  <a href="eval.html#:while">:while</a>  或  <a href="eval.html#:for">:for</a>  循环的内部，跳回循环开始的地方。
                        如果在循环内部的  <a href="eval.html#:try">:try</a>  之后但在匹配的  <a href="eval.html#:finally">:finally</a>  (如
                        果有的话) 之前， <a href="eval.html#:finally">:finally</a>  之后，匹配的  <a href="eval.html#:endtry">:endtry</a>  之前
                        的命令会被先执行。该过程反复应用于所有函数内的嵌套
                         <a href="eval.html#:try">:try</a>  块。在最外层  <a href="eval.html#:endtry">:endtry</a>  结束之后才跳回循环的开始
                        处。

                         <a href="vim9.html#Vim9">Vim9</a>  脚本里  <code class="badlink">:cont</code>  是最短的形式，以提高脚本的可读
                        性。
                                                <b class="vimtag"> <a name=":break">:break</a> </b> <b class="vimtag"> <a name=":brea">:brea</a> </b> <b class="vimtag"> <a name="E587">E587</a> </b>
:brea[k]                在  <a href="eval.html#:while">:while</a>  或  <a href="eval.html#:for">:for</a>  循环的内部，跳到相匹配的
                         <a href="eval.html#:endwhile">:endwhile</a>  或  <a href="eval.html#:endfor">:endfor</a>  之后的命令。
                        如果在循环内部的  <a href="eval.html#:try">:try</a>  之后但在匹配的  <a href="eval.html#:finally">:finally</a>  (如
                        果有的话) 之前， <a href="eval.html#:finally">:finally</a>  之后，匹配的  <a href="eval.html#:endtry">:endtry</a>  之前
                        的命令会被先执行。该过程反复应用于所有函数内的嵌套
                         <a href="eval.html#:try">:try</a>  块。在最外层  <a href="eval.html#:endtry">:endtry</a>  结束之后才跳到循环之后的
                        命令。

                         <a href="vim9.html#Vim9">Vim9</a>  脚本里  <a href="eval.html#:break">:break</a>  不能用短形式，以提高脚本的可读
                        性。

:try                                            <b class="vimtag"> <a name=":try">:try</a> </b> <b class="vimtag"> <a name=":endt">:endt</a> </b> <b class="vimtag"> <a name=":endtry">:endtry</a> </b>
                                                <b class="vimtag"> <a name="E600">E600</a> </b> <b class="vimtag"> <a name="E601">E601</a> </b> <b class="vimtag"> <a name="E602">E602</a> </b> <b class="vimtag"> <a name="E1032">E1032</a> </b>
:endt[ry]               改变  <a href="eval.html#:try">:try</a>  和  <a href="eval.html#:endtry">:endtry</a>  之间命令的错误处理，包括所有
                        执行的内容， <a href="repeat.html#:source">:source</a>  里的命令，函数调用，或者自动命令
                        的激活等。

                        如果检测到错误或者中断，而其后又跟随了  <a href="eval.html#:finally">:finally</a>  命
                        令，执行从  <a href="eval.html#:finally">:finally</a>  之后继续。否则，或者在那以后遇到
                        了  <a href="eval.html#:endtry">:endtry</a> ，则检查是否存在 (动态的) 往外一层的
                         <a href="eval.html#:try">:try</a>  以及其相应的  <a href="eval.html#:finally">:finally</a>  等等。然后，脚本的处理
                        被终止。函数定义里是否有 "abort" 参数都不相干。
                        示例: 
<code class="example">                try | call Unknown() | finally | echomsg "cleanup" | endtry</code>
<code class="example">                echomsg "not reached"</code>

                        另外， <a href="eval.html#:try">:try</a>  和  <a href="eval.html#:endtry">:endtry</a>  之间的错误或者中断 (动态地)
                        被转换成一个例外。它的捕获过程如同它被  <a href="eval.html#:throw">:throw</a>  命令抛
                        出那样 (见  <a href="eval.html#:catch">:catch</a> )。这种情况下，脚本的处理不会被终
                        止。

                        "Vim:Interrupt" 的值用于中断例外。Vim 命令的错误被转换
                        成形如 "Vim(<code class="special">{command}</code>):<code class="special">{errmsg}</code>" 的值，其它错误被转换
                        成形如 "Vim:<code class="special">{errmsg}</code>"。这里，<code class="special">{command}</code> 是完整的命令
                        名，而 <code class="special">{errmsg}</code> 是错误例外如果没有被捕获的时候会显示的
                        消息，它总以错误号开始。
                        示例: 
<code class="example">                try | sleep 100 | catch /^Vim:Interrupt$/ | endtry</code>
<code class="example">                try | edit | catch /^Vim(edit):E\d\+/ | echo "error" | endtry</code>

                                        <b class="vimtag"> <a name=":cat">:cat</a> </b> <b class="vimtag"> <a name=":catch">:catch</a> </b>
                                        <b class="vimtag"> <a name="E603">E603</a> </b> <b class="vimtag"> <a name="E604">E604</a> </b> <b class="vimtag"> <a name="E605">E605</a> </b> <b class="vimtag"> <a name="E654">E654</a> </b> <b class="vimtag"> <a name="E1033">E1033</a> </b>
:cat[ch] /<code class="special">{pattern}</code>/    匹配 <code class="special">{pattern}</code> 的例外抛出时，如果它没有被前一个
                         <a href="eval.html#:catch">:catch</a>  捕获，则执行本语句之后的命令，直到遇到和本
                         <a href="eval.html#:catch">:catch</a>  处于同一  <a href="eval.html#:try">:try</a>  块的下一个  <a href="eval.html#:catch">:catch</a> 、
                        `:finally `或者  <a href="eval.html#:endtry">:endtry</a>  为止。否则，这些命令被跳过。
                        如果没有提供 <code class="special">{pattern}</code>，所有的错误都会被捕获。
                        示例: 
<code class="example">                :catch /^Vim:Interrupt$/         " 捕获中断 (CTRL-C)</code>
<code class="example">                :catch /^Vim\%((\a\+)\)\=:E/     " 捕获所有的 Vim 错误</code>
<code class="example">                :catch /^Vim\%((\a\+)\)\=:/      " 捕获错误和中断</code>
<code class="example">                :catch /^Vim(write):/            " 捕获所有 :write 的错误</code>
<code class="example">                :catch /^Vim\%((\a\+)\)\=:E123:/ " 捕获错误 E123</code>
<code class="example">                :catch /my-exception/            " 捕获用户例外</code>
<code class="example">                :catch /.*/                      " 捕获一切</code>
<code class="example">                :catch                           " 同 /.*/</code>

                        除了 / 以外，也可以用别的字符包围 <code class="special">{pattern}</code>，只要它没
                        有特殊含义 (比如 '|' 或 '"') 而且不出现在 <code class="special">{pattern}</code>
                        里。 <b class="vimtag"> <a name="E1067">E1067</a> </b>
                        关于例外的信息可见  <a href="eval.html#v:exception">v:exception</a> 。另见
                         <a href="eval.html#throw-variables">throw-variables</a> 。
                        <code class="note">注意</code>: 依赖 ":catch" 去捕获错误信息的 <code class="emphasis">文本</code> 是不可靠的，
                        因为不同的 locale 的信息可以不同。
                         <a href="vim9.html#Vim9">Vim9</a>  脚本里  <a href="eval.html#:catch">:catch</a>  不能用短形式，以提高脚本的可读
                        性。

                                        <b class="vimtag"> <a name=":fina">:fina</a> </b> <b class="vimtag"> <a name=":finally">:finally</a> </b> <b class="vimtag"> <a name="E606">E606</a> </b> <b class="vimtag"> <a name="E607">E607</a> </b>
:fina[lly]              任何匹配的  <a href="eval.html#:try">:try</a>  和本  <a href="eval.html#:finally">:finally</a>  之间的部分要离开的时
                        候都执行本语句之后的命令，直到遇到匹配的  <a href="eval.html#:endtry">:endtry</a>  为
                        止。包括这些情形: 正常完成且要执行到  <a href="eval.html#:finally">:finally</a> ，通过
                         <a href="eval.html#:continue">:continue</a> 、 <a href="eval.html#:break">:break</a> 、 <a href="repeat.html#:finish">:finish</a>  或  <a href="userfunc.html#:return">:return</a> ，或者由
                        于错误或者中断或者例外 (见  <a href="eval.html#:throw">:throw</a> )。

                         <a href="vim9.html#Vim9">Vim9</a>  脚本里  <a href="eval.html#:finally">:finally</a>  不能用短形式，以提高脚本的可
                        读性并和  <a href="vim9.html#:final">:final</a>  混淆。

                                                <b class="vimtag"> <a name=":th">:th</a> </b> <b class="vimtag"> <a name=":throw">:throw</a> </b> <b class="vimtag"> <a name="E608">E608</a> </b> <b class="vimtag"> <a name="E1129">E1129</a> </b>
:th[row] <code class="special">{expr1}</code>        计算 <code class="special">{expr1}</code> 然后抛出例外。如果  <a href="eval.html#:throw">:throw</a>  在  <a href="eval.html#:try">:try</a>  之
                        后但在第一个对应的  <a href="eval.html#:catch">:catch</a>  之前使用，它之后的命令被跳
                        过，直到遇到第一个匹配 <code class="special">{expr1}</code> 为止。如果没有这样的
                         <a href="eval.html#:catch">:catch</a> ，或者如果  <a href="eval.html#:throw">:throw</a>  在  <a href="eval.html#:catch">:catch</a>  之后
                         <a href="eval.html#:finally">:finally</a>  之前使用，执行  <a href="eval.html#:finally">:finally</a>  (如果有的话) 之后
                        直到匹配的  <a href="eval.html#:endtry">:endtry</a>  为止的命令。如果本  <a href="eval.html#:throw">:throw</a>  在
                         <a href="eval.html#:finally">:finally</a>  之后之后出现，直到  <a href="eval.html#:endtry">:endtry</a>  为止的命令都被
                        跳过。到达  <a href="eval.html#:endtry">:endtry</a>  的时候，在动态计算的往外一层的
                         <a href="eval.html#:try">:try</a>  块上再次重复本过程 (这可能出现在外层调用的函数
                        或者执行的脚本上)，直到找到一个匹配的  <a href="eval.html#:catch">:catch</a> 。如果最
                        终该例外没有被捕获，命令处理被终止。
                        示例: 
<code class="example">                :try | throw "oops" | catch /^oo/ | echo "caught" | endtry</code>
                        <code class="note">注意</code>  <code class="badlink">catch</code>  可能需要放在单独一行上，因为某些错误可以
                        导致整行在解析时被跳过而无法看到分隔命令的 "|"。

                         <a href="vim9.html#Vim9">Vim9</a>  脚本里  <a href="eval.html#:throw">:throw</a>  不能用短形式，以提高脚本的可读
                        性。

                                                        <b class="vimtag"> <a name=":ec">:ec</a> </b> <b class="vimtag"> <a name=":echo">:echo</a> </b>
:ec[ho] <code class="special">{expr1}</code> ..      回显每个 <code class="special">{expr1}</code>，以空格分隔。第一个 <code class="special">{expr1}</code> 开启一个
                        新行。另见  <a href="cmdline.html#:comment">:comment</a> 。
                        使用 "\n" 来开启新行。使用 "\r" 把光标移到第一列。
                        使用  <a href="eval.html#:echohl">:echohl</a>  命令的高亮设置。
                        后面不能跟注释。
                        示例: 
<code class="example">                :echo "'shell' 的值是 " &amp;shell</code>
                                                        <b class="vimtag"> <a name=":echo-redraw">:echo-redraw</a> </b>
                        后来的重画可能使消息再次消失。因为 Vim 常常会推迟重画
                        直到整个命令序列执行完为止，这个问题会频繁出现。要避免
                         <a href="eval.html#:echo">:echo</a>  之前的命令引起它之后的重画 (通常，重画被延迟到
                        有输入的时候才进行)，使用  <a href="various.html#:redraw">:redraw</a>  命令强制重画。例
                        如: 
<code class="example">                :new | redraw | echo "这里有一个新窗口"</code>

                                                        <b class="vimtag"> <a name=":echon">:echon</a> </b>
:echon <code class="special">{expr1}</code> ..       回显每个 <code class="special">{expr1}</code>，不附加其它字符。另见  <a href="cmdline.html#:comment">:comment</a> 。
                        使用  <a href="eval.html#:echohl">:echohl</a>  命令的高亮设置。
                        后面不能跟注释。
                        例如: 
<code class="example">                                :echon "'shell' 的值是 " &amp;shell</code>

                        <code class="note">注意</code> 两者的区别:  <a href="eval.html#:echo">:echo</a>  是一个 Vim 命令，而  <code class="badlink">:!echo</code> 
                        是一个外部的外壳命令: 
<code class="example">                :!echo %                --&gt; filename</code>
                        ":!" 的参数被扩展，见  <a href="cmdline.html#:_%">:_%</a> 。 
<code class="example">                :!echo "%"              --&gt; filename or "filename"</code>
                        和前例类似，你是否会看到双引号取决于你的 <a href="options.html#'shell'">'shell'</a>。 
<code class="example">                :echo %                 --&gt; nothing</code>
                        '%' 不是一个表达式合法的字符。 
<code class="example">                :echo "%"               --&gt; %</code>
                        只会回显 '%' 字符。 
<code class="example">                :echo expand("%")       --&gt; filename</code>
                        调用 expand() 函数来扩展 '%'。

                                                        <b class="vimtag"> <a name=":echoh">:echoh</a> </b> <b class="vimtag"> <a name=":echohl">:echohl</a> </b>
:echoh[l] <code class="special">{name}</code>        让其后的  <a href="eval.html#:echo">:echo</a> 、 <a href="eval.html#:echon">:echon</a>  和  <a href="eval.html#:echomsg">:echomsg</a>  命令使用高亮
                        组 <code class="special">{name}</code>。也可用于  <a href="builtin.html#input()">input()</a>  的提示。示例: 
<code class="example">                :echohl WarningMsg | echo "Don't panic!" | echohl None</code>
                        不要忘记把组设回 "None"。不然其后的 echo 都会被高亮。

                                                        <b class="vimtag"> <a name=":echom">:echom</a> </b> <b class="vimtag"> <a name=":echomsg">:echomsg</a> </b>
:echom[sg] <code class="special">{expr1}</code> ..   回显表达式的结果，将其作为一个真正的消息，并把该消息保
                        存在  <a href="message.html#message-history">message-history</a>  里。
                        参数之间加入空格，和  <a href="eval.html#:echo">:echo</a>  类似。但不可显示的字符只
                        是回显而不会被解释。
                        这里的分析过程和  <a href="eval.html#:echo">:echo</a>  略有不同，而更像  <a href="eval.html#:execute">:execute</a> 。
                        所有的表达式都先经计算后进行连接，然后再进行回显。
                        如果表达式返回的不是数值或字符串，使用 string() 把它转
                        化为字符串。
                        应用  <a href="eval.html#:echohl">:echohl</a>  命令的高亮设置。
                        示例: 
<code class="example">                :echomsg "It's a Zizzer Zazzer Zuzz, as you can plainly see."</code>
                         <a href="eval.html#:echo-redraw">:echo-redraw</a>  说明如何避免屏幕重画时消息的消失问题。

                                        <b class="vimtag"> <a name=":echow">:echow</a> </b> <b class="vimtag"> <a name=":echowin">:echowin</a> </b> <b class="vimtag"> <a name=":echowindow">:echowindow</a> </b>
:[N]echow[indow] <code class="special">{expr1}</code> ..
                        类似于  <a href="eval.html#:echomsg">:echomsg</a> ，但如消息弹出窗口可用，在那里显示消
                        息。会显示三秒后消失，而省去了  <a href="message.html#hit-enter">hit-enter</a>  提示。如果
                        要在那之前就要隐藏，可在普通模式下按 Esc (否则会响铃)。
                        如果消失太快了也没关系， <a href="message.html#:messages">:messages</a>  还是可以看到文本。
                        <code class="special">[N]</code> 给出时窗口会停留给定的秒数。只有最近一次带计数的
                         <a href="eval.html#:echowindow">:echowindow</a>  的计数有效，且仅当次有效。
                        仅当 Vim 编译时加入了 +timer 和 +popupwin 特性时消息窗
                        口才可用。

                                                        <b class="vimtag"> <a name=":echoe">:echoe</a> </b> <b class="vimtag"> <a name=":echoerr">:echoerr</a> </b>
:echoe[rr] <code class="special">{expr1}</code> ..   回显表达式的结果，将其作为一个错误消息，并把该消息保
                        存在  <a href="message.html#message-history">message-history</a>  里。如果用在脚本或函数里，会加
                        入行号。
                        参数之间加入空格的方法和  <a href="eval.html#:echomsg">:echomsg</a>  类似。如果在 try
                        条件句里使用，该消息会抛出一个错误例外 (见
                         <a href="eval.html#try-echoerr">try-echoerr</a> )。
                        示例: 
<code class="example">                :echoerr "This script just failed!"</code>
                        如果你只想要使用  <a href="eval.html#:echohl">:echohl</a>  高亮的消息。
                        要得到铃声: 
<code class="example">                :exe "normal \&lt;Esc&gt;"</code>


:echoc[onsole] <code class="special">{expr1}</code> ..                               <b class="vimtag"> <a name=":echoc">:echoc</a> </b> <b class="vimtag"> <a name=":echoconsole">:echoconsole</a> </b>
                        用于测试: 类似于  <a href="eval.html#:echomsg">:echomsg</a>  但在 GUI 中运行且原来从终
                        端启动时，把文本写到标准输出。

                                                        <b class="vimtag"> <a name=":eval">:eval</a> </b>
:eval <code class="special">{expr}</code>            计算 <code class="special">{expr}</code> 并忽略其返回值。例如: 
<code class="example">                                :eval Getlist()-&gt;Filter()-&gt;append('$')</code>
<code class="example"></code>
                        因为不使用返回值，表达式假定有副作用。此例中
                         <a href="builtin.html#append()">append()</a>  调用会在缓冲区后附加列表中的文本。它类似于
                         <a href="userfunc.html#:call">:call</a> ，但可用于所有表达式。
                         <a href="vim9.html#Vim9">Vim9</a>  脚本里没有副作用的表达式会报错 <b class="vimtag"> <a name="E1207">E1207</a> </b> 。这有助
                        于发现问题。

                        此命令本可缩短为  <code class="badlink">:ev</code>  或  <code class="badlink">:eva</code> ，但不易记，所以不提
                        供。

                        此命令不能后跟 "|" 加其它命令，因为 "|" 视为表达式的一
                        部分。


                                                        <b class="vimtag"> <a name=":exe">:exe</a> </b> <b class="vimtag"> <a name=":execute">:execute</a> </b>
:exe[cute] <code class="special">{expr1}</code> ..   计算 <code class="special">{expr1}</code>，返回的字符串作为 Ex 命令执行。
                        多个参数用空格连接。如果不想有额外的空格，使用 ".." 操
                        作符来连接字符串使之成为一个参数。
                        <code class="special">{expr1}</code> 用作被处理的命令，命令行编辑的键不会被识别。
                        后面不能跟注释。
                        示例: 
<code class="example">                :execute "buffer" nextbuf</code>
<code class="example">                :execute "normal" count .. "w"</code>

                        ":execute" 可以用来把命令附加到不能接受 '|' 的命令后
                        面。比如: 
<code class="example">                :execute '!ls' | echo "theend"</code>
<code class="example"></code>
                        ":execute" 也是一个避免在 Vim 脚本里为 ":normal" 命令
                        输入控制字符的好方法: 
<code class="example">                :execute "normal ixxx\&lt;Esc&gt;"</code>
                        这里给出一个 <code class="special">&lt;Esc&gt;</code> 字符，见  <a href="eval.html#expr-string">expr-string</a> 。

                        要谨慎对待文件名中特殊字符的正确转义。 <a href="builtin.html#fnameescape()">fnameescape()</a> 
                        可用于 Vim 命令， <a href="builtin.html#shellescape()">shellescape()</a>  可用于  <a href="various.html#:!">:!</a>  命令。示
                        例: 
<code class="example">                :execute "e " .. fnameescape(filename)</code>
<code class="example">                :execute "!ls " .. shellescape(filename, 1)</code>

                        <code class="note">注意</code>: 执行的字符串可以是任何命令行，但开始或结束一个
                        "if"、"while" 和 "for" 命令不能保证没有问题，因为跳过
                        命令时，不执行 ":execute"，Vim 就不能准确找到块开始和
                        结束的地方。另外，"break" 和 "continue" 不应出现在
                        ":execute" 内部。
                        下例不能工作，因为 ":execute" 不被执行，Vim 看不见
                        ":while"，找到 ":endwhile" 时就报错: 
<code class="example">                :if 0</code>
<code class="example">                : execute 'while i &gt; 5'</code>
<code class="example">                :  echo "test"</code>
<code class="example">                : endwhile</code>
<code class="example">                :endif</code>

                        但如果执行的字符串里有完整的 "while" 和 "if" 命令就没
                        有问题: 
<code class="example">                :execute 'while i &lt; 5 | echo i | let i = i + 1 | endwhile'</code>


                                                        <b class="vimtag"> <a name=":exe-comment">:exe-comment</a> </b>
                        ":execute"、":echo" 和 ":echon" 后面不能直接跟注释。
                        因它们把 '"' 看成字符串的开始。但你可以把注释加到 '|'
                        后面。例如: 
<code class="example">                :echo "foo" | "这是一个注释</code>
<code class="example"></code>
</section><hr class="doubleline" /><section class=inner>
<h4>8. 例外处理                                             <b class="vimtag"> <a name="exception-handling">exception-handling</a> </b></h4>
Vim 脚本语言包含了例外处理特性。本节解释如何在 Vim 脚本里应用该机制。

Vim 在出错或者中断的时候可以抛出例外。见  <a href="eval.html#catch-errors">catch-errors</a>  和  <a href="eval.html#catch-interrupt">catch-interrupt</a> 。
你也可以显式地使用 ":throw" 命令抛出例外。见  <a href="eval.html#throw-catch">throw-catch</a> 。


TRY 条 件 句                                            <b class="vimtag"> <a name="try-conditionals">try-conditionals</a> </b>

例外可以被捕获或者用来激发清理代码的运行。你可以使用 try 条件句来指定 catch 子
句 (捕获例外) 和/或 finally 子句 (执行清理)。
   try 条件句以  <a href="eval.html#:try">:try</a>  命令开始，以匹配的  <a href="eval.html#:endtry">:endtry</a>  命令结束。两者之间，你可以
使用  <a href="eval.html#:catch">:catch</a>  命令开始 catch 子句，或者用  <a href="eval.html#:finally">:finally</a>  命令开始 finally 子句。
catch 子句可有零到多个，但 finally 子句至多只有一个，且它之后不能再有 catch 子
句。catch 子句和 finally 子句之前的行称为 try 块。

     :try
     :  ...
     :  ...                             TRY 块
     :  ...
     :catch /<code class="special">{pattern}</code>/
     :  ...
     :  ...                             CATCH 子 句
     :  ...
     :catch /<code class="special">{pattern}</code>/
     :  ...
     :  ...                             CATCH 子 句
     :  ...
     :finally
     :  ...
     :  ...                             FINALLY 子 句
     :  ...
     :endtry

try 子句允许观察代码里是否有例外，并采取合适的行动。try 块里的例外可能被捕获。
try 块和 catch 子句里的例外可能引起清理动作。
   如果 try 块的执行过程中没有抛出例外，控制转移到 finally 子句。在它执行后，
脚本从 ":endtry" 之后的行继续。
   如果 try 块的执行过程中抛出了例外，该 try 块其余的行被跳过。例外和 ":catch"
命令的模式参数一一比较。第一个匹配的 ":catch" 之后的 catch 子句被采用，其余的
catch 子句则不会执行。catch 子句在下一个最早遇到的 ":catch"、":finally" 或
":endtry" 命令结束。这时，finally 子句 (如果有的话) 被执行。当遇到 ":endtry"
的时候，脚本从后面的行继续，一如往常。
   如果 try 块抛出的例外不能匹配任何 ":catch" 命令的模式，该例外不能由本 try
条件句捕获，因而不会执行任何的 catch 子句。只有 finally 子句，如果有的话，被采
用。该例外在 finally 子句的执行时被暂时搁置。在 ":endtry" 之后才继续。这样，
":endtry" 之后的命令不会被执行，而该例外可以在别的地方捕获，见  <a href="eval.html#try-nesting">try-nesting</a> 。
   如果在 catch 子句的执行过程中抛出了另一个错误，catch 子句的其余部分不再执
行。新的例外不会和试图和同一个 try 条件句的任何 ":catch" 命令的模式匹配，因而
也不会执行任何它的 catch 子句。不过，如果有 finally 子句，它还是会被执行，而在
它的执行过程中暂时搁置新的例外。":endtry" 之后的命令也不会执行。而新的例外仍可
能在别的地方捕获，见  <a href="eval.html#try-nesting">try-nesting</a> 。
   如果在 finally 子句 (如果有的话) 的执行过程中抛出了另一个错误，finally 子句
的其余部分不再执行。如果 finally 子句是因为 try 块或者某个 catch 子句里产生的
例外引起的，原先的 (被暂时搁置的) 例外被放弃。":endtry" 之后的命令也不会执行。
而 finally 子句的这个例外被传播，而可以在别的地方捕获，见  <a href="eval.html#try-nesting">try-nesting</a> 。

在 ":while" 循环包含的完整的 try 条件句里的 try 块或者某个 catch 子句里遇到
":break" 或 ":continue" 时，或者在函数或者被执行的脚本里的 try 条件句里的 try
块或者某个 catch 子句里执行 ":return" (函数) 或者 ":finish" (脚本) 的时候，也
会执行 finally 子句。":break"、":continue"、":return" 或者 ":finish" 在
finally 子句的执行时被暂停，而在遇到 ":endtry" 时继续。不过，如果在执行
finally 子句时抛出例外，它们都被抛弃。
   在 ":while" 循环包含的完整的 try 条件句里的 finally 子句里遇到 ":break" 或
":continue" 时，或者在函数或者被执行的脚本里的 finally 子句里执行 ":return" (
函数) 或者 ":finish" (脚本) 的时候，finally 子句的其余部分被跳过，而
":break"、":continue"、":return" 或 ":finish" 会如常继续执行。如果 finally 的
执行是因为例外或者早先的 try 块或者 catch 子句的 ":break"、":continue"、
":return" 或者 ":finish" 引起的，暂停的例外或者命令被放弃。

例子可见  <a href="eval.html#throw-catch">throw-catch</a>  和  <a href="eval.html#try-finally">try-finally</a> 。


TRY 条 件 句 的 嵌 套                                   <b class="vimtag"> <a name="try-nesting">try-nesting</a> </b>

try 条件句可以任意嵌套。也就是说，完整的 try 条件句可以在另一个 try 条件句的
try 块、某个 catch 子句或者 finally 子句里出现。如果内层的 try 条件句不能捕获
它的 try 块抛出的例外，或者在它的某个 catch 子句后者 finally 子句里抛出新的例
外的话，那么根据上述规则由外层的 try 条件句继续检查是否能捕获该例外。如果内层
try 条件句在外层 try 条件句的 try 块里，检查外层的 catch 子句，不然只有
finally 子句会被执行。对嵌套的处理而言，内层 try 条件句是直接包含在外层里面，
还是外层执行了脚本或者调用了函数，而后者又包含了内层 try 条件句，无关紧要。

如果没有活动的 try 条件句能捕获某个例外，只有它们的 finally 子句会执行。最后，
脚本结束它的处理。如果是 ":throw" 命令显式地抛出的未捕获的例外，显示错误信息。
对于 Vim 隐含抛出的未捕获的错误或者中断例外，错误信息或者中断信息也会像平常一
样显示。

例子可见  <a href="eval.html#throw-catch">throw-catch</a> 。


检 查 例 外 处 理 代 码                                 <b class="vimtag"> <a name="except-examine">except-examine</a> </b>

例外处理的代码的编写可能很麻烦。如果你不知道发生了什么，把 <a href="options.html#'verbose'">'verbose'</a> 设为 13，
或者在执行脚本文件时使用 ":13verbose" 命令修饰符。这样，你能看到什么时候例外被
抛出、放弃、捕获、或者最终处理。如果详细程度大于等于 14，finally 子句暂停什么
也会显示。这些信息在调试模式里也会给出 (见  <a href="repeat.html#debug-scripts">debug-scripts</a> )。


抛 出 和 捕 获 例 外                                    <b class="vimtag"> <a name="throw-catch">throw-catch</a> </b>

你可以抛出任何数值或者字符串作为例外。使用  <a href="eval.html#:throw">:throw</a>  命令然后把要抛出的值作为参
数传入: 
<code class="example">        :throw 4711</code>
<code class="example">        :throw "string"</code>
                                                        <b class="vimtag"> <a name="throw-expression">throw-expression</a> </b>
你可以指定表达式参数。该表达式先进行计算，然后抛出其结果: 
<code class="example">        :throw 4705 + strlen("string")</code>
<code class="example">        :throw strpart("strings", 0, 6)</code>
<code class="example"></code>
在计算 ":throw" 命令的参数的时候，也可能会抛出例外。除非它被捕获，不然表达式的
计算会被放弃。":throw" 命令这时不会抛出新的例外。
   例如: 
<code class="example"></code>
<code class="example">        :function! Foo(arg)</code>
<code class="example">        :  try</code>
<code class="example">        :    throw a:arg</code>
<code class="example">        :  catch /foo/</code>
<code class="example">        :  endtry</code>
<code class="example">        :  return 1</code>
<code class="example">        :endfunction</code>
<code class="example">        :</code>
<code class="example">        :function! Bar()</code>
<code class="example">        :  echo "in Bar"</code>
<code class="example">        :  return 4710</code>
<code class="example">        :endfunction</code>
<code class="example">        :</code>
<code class="example">        :throw Foo("arrgh") + Bar()</code>
<code class="example"></code>
这里抛出了 "arrgh"，而不会显示 "in Bar"，因为 Bar() 没有执行。 
<code class="example">        :throw Foo("foo") + Bar()</code>
却显示 "in Bar" 并且抛出 4711。

别的接受表达式作为参数的命令也可能因为表达式计算过程的 (未捕获的) 例外而被放
弃。例外这时被传播给该命令的调用者。
   例如: 
<code class="example"></code>
<code class="example">        :if Foo("arrgh")</code>
<code class="example">        :  echo "then"</code>
<code class="example">        :else</code>
<code class="example">        :  echo "else"</code>
<code class="example">        :endif</code>
<code class="example"></code>
这里 "then" 和 "else" 都不会显示。

                                                        <b class="vimtag"> <a name="catch-order">catch-order</a> </b>
try 条件句里的例外可以用一个或多个  <a href="eval.html#:catch">:catch</a>  命令捕获，见  <a href="eval.html#try-conditionals">try-conditionals</a> 。
每个 ":catch" 命令可以捕获的值通过模式参数指定。捕获匹配的例外时，执行其后的
catch 子句。
   例如: 
<code class="example"></code>
<code class="example">        :function! Foo(value)</code>
<code class="example">        :  try</code>
<code class="example">        :    throw a:value</code>
<code class="example">        :  catch /^\d\+$/</code>
<code class="example">        :    echo "Number thrown"</code>
<code class="example">        :  catch /.*/</code>
<code class="example">        :    echo "String thrown"</code>
<code class="example">        :  endtry</code>
<code class="example">        :endfunction</code>
<code class="example">        :</code>
<code class="example">        :call Foo(0x1267)</code>
<code class="example">        :call Foo('string')</code>
<code class="example"></code>
第一个 Foo() 的调用显示 "Number thrown"，第二个 "String thrown"。
按照 ":catch" 命令本身的顺序，依次匹配例外。只用第一个成功匹配。所以，你应该把
更专门的 ":catch" 放在前面。下面的顺序并不合理: 
<code class="example"></code>
<code class="example">        :  catch /.*/</code>
<code class="example">        :    echo "String thrown"</code>
<code class="example">        :  catch /^\d\+$/</code>
<code class="example">        :    echo "Number thrown"</code>
<code class="example"></code>
这里，第一个 ":catch" 总是会被匹配，所以第二个子句永远不可能被采用。

                                                        <b class="vimtag"> <a name="throw-variables">throw-variables</a> </b>
如果你使用通用的模式捕获到例外，可以通过变量  <a href="eval.html#v:exception">v:exception</a>  得到准确的例外值: 
<code class="example"></code>
<code class="example">        :  catch /^\d\+$/</code>
<code class="example">        :    echo "Number thrown.  Value is" v:exception</code>
<code class="example"></code>
你也许会对在什么地方抛出例外也感兴趣。它被保存在  <a href="eval.html#v:throwpoint">v:throwpoint</a>  里。<code class="note">注意</code>
"v:exception" 和 "v:throwpoint" 可用于最近捕获的例外，只要该例外还没有完成处
理。
   例如: 
<code class="example"></code>
<code class="example">        :function! Caught()</code>
<code class="example">        :  if v:exception != ""</code>
<code class="example">        :    echo 'Caught "' .. v:exception .. '" in ' .. v:throwpoint</code>
<code class="example">        :  else</code>
<code class="example">        :    echo 'Nothing caught'</code>
<code class="example">        :  endif</code>
<code class="example">        :endfunction</code>
<code class="example">        :</code>
<code class="example">        :function! Foo()</code>
<code class="example">        :  try</code>
<code class="example">        :    try</code>
<code class="example">        :      try</code>
<code class="example">        :        throw 4711</code>
<code class="example">        :      finally</code>
<code class="example">        :        call Caught()</code>
<code class="example">        :      endtry</code>
<code class="example">        :    catch /.*/</code>
<code class="example">        :      call Caught()</code>
<code class="example">        :      throw "oops"</code>
<code class="example">        :    endtry</code>
<code class="example">        :  catch /.*/</code>
<code class="example">        :    call Caught()</code>
<code class="example">        :  finally</code>
<code class="example">        :    call Caught()</code>
<code class="example">        :  endtry</code>
<code class="example">        :endfunction</code>
<code class="example">        :</code>
<code class="example">        :call Foo()</code>
<code class="example"></code>
会显示 
<code class="example"></code>
<code class="example">        Nothing caught</code>
<code class="example">        Caught "4711" in function Foo, line 4</code>
<code class="example">        Caught "oops" in function Foo, line 10</code>
<code class="example">        Nothing caught</code>
<code class="example"></code>
更实际的例子:  下面的命令 ":LineNumber" 显示调用它时，脚本或者函数里的行号: 
<code class="example"></code>
<code class="example">        :function! LineNumber()</code>
<code class="example">        :    return substitute(v:throwpoint, '.*\D\(\d\+\).*', '\1', "")</code>
<code class="example">        :endfunction</code>
<code class="example">        :command! LineNumber try | throw "" | catch | echo LineNumber() | endtry</code>

                                                        <b class="vimtag"> <a name="try-nested">try-nested</a> </b>
try 条件句没有捕获的例外可以在包围它的 try 条件句中捕获: 
<code class="example"></code>
<code class="example">        :try</code>
<code class="example">        :  try</code>
<code class="example">        :    throw "foo"</code>
<code class="example">        :  catch /foobar/</code>
<code class="example">        :    echo "foobar"</code>
<code class="example">        :  finally</code>
<code class="example">        :    echo "inner finally"</code>
<code class="example">        :  endtry</code>
<code class="example">        :catch /foo/</code>
<code class="example">        :  echo "foo"</code>
<code class="example">        :endtry</code>
<code class="example"></code>
内层的 try 条件句没有捕获例外，只执行了 finally 子句。例外在外层得到捕获。本例
显示 "inner finally" 然后是 "foo"。

                                                        <b class="vimtag"> <a name="throw-from-catch">throw-from-catch</a> </b>
你可以捕获某例外，然后抛出另一个。它在该 catch 子句之外捕获: 
<code class="example"></code>
<code class="example">        :function! Foo()</code>
<code class="example">        :  throw "foo"</code>
<code class="example">        :endfunction</code>
<code class="example">        :</code>
<code class="example">        :function! Bar()</code>
<code class="example">        :  try</code>
<code class="example">        :    call Foo()</code>
<code class="example">        :  catch /foo/</code>
<code class="example">        :    echo "Caught foo, throw bar"</code>
<code class="example">        :    throw "bar"</code>
<code class="example">        :  endtry</code>
<code class="example">        :endfunction</code>
<code class="example">        :</code>
<code class="example">        :try</code>
<code class="example">        :  call Bar()</code>
<code class="example">        :catch /.*/</code>
<code class="example">        :  echo "Caught" v:exception</code>
<code class="example">        :endtry</code>
<code class="example"></code>
显示 "Caught foo, throw bar" 然后是 "Caught bar"。

                                                        <b class="vimtag"> <a name="rethrow">rethrow</a> </b>
Vim 脚本语言没有真正的 rethrow。但可以抛出 "v:exception" 来代替: 
<code class="example"></code>
<code class="example">        :function! Bar()</code>
<code class="example">        :  try</code>
<code class="example">        :    call Foo()</code>
<code class="example">        :  catch /.*/</code>
<code class="example">        :    echo "Rethrow" v:exception</code>
<code class="example">        :    throw v:exception</code>
<code class="example">        :  endtry</code>
<code class="example">        :endfunction</code>
                                                        <b class="vimtag"> <a name="try-echoerr">try-echoerr</a> </b>
<code class="note">注意</code> 这个方法不能用来 "rethrow" Vim 错误或者中断例外，因为不能伪造 Vim 的内部
例外。试图这么做会产生一个错误例外。你应该抛出自己的例外来说明这种情形。如果你
想产生 Vim 的错误例外并包含原来的错误例外的值，可以使用  <a href="eval.html#:echoerr">:echoerr</a>  命令: 
<code class="example"></code>
<code class="example">        :try</code>
<code class="example">        :  try</code>
<code class="example">        :    asdf</code>
<code class="example">        :  catch /.*/</code>
<code class="example">        :    echoerr v:exception</code>
<code class="example">        :  endtry</code>
<code class="example">        :catch /.*/</code>
<code class="example">        :  echo v:exception</code>
<code class="example">        :endtry</code>
<code class="example"></code>
本代码会显示

<code class="section">        Vim(echoerr):Vim:E492: Not an editor command:   asdf </code>


清 理 代 码                                             <b class="vimtag"> <a name="try-finally">try-finally</a> </b>

脚本经常需要改变全局设定然后结束时恢复之。不过，如果用户按了 <code class="keystroke">CTRL-C</code> 中止脚本，
这些设定会处于不一致的状态。如果你处于某脚本的开发阶段而发生了错误或者你显式地
抛出例外而没有试图捕获之，也会有相同的情况。用带有 finally 子句的 try 条件句，
可以恢复设置，从而解决这个问题。可以保证无论是正常的控制流、出错或者显式的例外
":throw"、还是被中断，都会执行 finally 子句 (<code class="note">注意</code> try 条件句的错误和中断被转换
成例外。如果没有捕获，它们在 finally 子句执行完之后会终止脚本。)
例如: 
<code class="example"></code>
<code class="example">        :try</code>
<code class="example">        :  let s:saved_ts = &amp;ts</code>
<code class="example">        :  set ts=17</code>
<code class="example">        :</code>
<code class="example">        :  " 这里执行重要的任务。</code>
<code class="example">        :</code>
<code class="example">        :finally</code>
<code class="example">        :  let &amp;ts = s:saved_ts</code>
<code class="example">        :  unlet s:saved_ts</code>
<code class="example">        :endtry</code>
<code class="example"></code>
无论任何函数还是脚本的一部分，只要它需要修改全局设置，而在失败或者成功退出该函
数或者脚本部分时需要恢复这些设置，就应该在本地应用本方法。

                                                        <b class="vimtag"> <a name="break-finally">break-finally</a> </b>
清理代码也适用于 ":continue"、":break"、":return" 或 ":finish" 退出的 try 块或
catch 子句。
   例如: 
<code class="example"></code>
<code class="example">        :let first = 1</code>
<code class="example">        :while 1</code>
<code class="example">        :  try</code>
<code class="example">        :    if first</code>
<code class="example">        :      echo "first"</code>
<code class="example">        :      let first = 0</code>
<code class="example">        :      continue</code>
<code class="example">        :    else</code>
<code class="example">        :      throw "second"</code>
<code class="example">        :    endif</code>
<code class="example">        :  catch /.*/</code>
<code class="example">        :    echo v:exception</code>
<code class="example">        :    break</code>
<code class="example">        :  finally</code>
<code class="example">        :    echo "cleanup"</code>
<code class="example">        :  endtry</code>
<code class="example">        :  echo "still in while"</code>
<code class="example">        :endwhile</code>
<code class="example">        :echo "end"</code>
<code class="example"></code>
会显示 "first"、"cleanup"、"second"、"cleanup" 和 "end"。 
<code class="example"></code>
<code class="example">        :function! Foo()</code>
<code class="example">        :  try</code>
<code class="example">        :    return 4711</code>
<code class="example">        :  finally</code>
<code class="example">        :    echo "cleanup\n"</code>
<code class="example">        :  endtry</code>
<code class="example">        :  echo "Foo still active"</code>
<code class="example">        :endfunction</code>
<code class="example">        :</code>
<code class="example">        :echo Foo() "returned by Foo"</code>
<code class="example"></code>
会显示 "cleanup" 和 "4711 returned by Foo"。你不需要在 finally 子句里加上附加
的 ":return"。(最终，它会覆盖原来的返回值。)

                                                        <b class="vimtag"> <a name="except-from-finally">except-from-finally</a> </b>
finally 子句里可以使用 ":continue"、":break"、":return"、":finish" 或
":throw"，但不推荐，因为它放弃了 try 条件句的清理工作。不过当然了，finally 子
句里仍然可能有中断或者错误例外。
   finally 子句的错误引起中断不能正常工作的例子: 
<code class="example"></code>
<code class="example">        :try</code>
<code class="example">        :  try</code>
<code class="example">        :    echo "Press CTRL-C for interrupt"</code>
<code class="example">        :    while 1</code>
<code class="example">        :    endwhile</code>
<code class="example">        :  finally</code>
<code class="example">        :    unlet novar</code>
<code class="example">        :  endtry</code>
<code class="example">        :catch /novar/</code>
<code class="example">        :endtry</code>
<code class="example">        :echo "Script still running"</code>
<code class="example">        :sleep 1</code>
<code class="example"></code>
如果你需要在 finally 里放入可能出错的命令，考虑捕获或者忽略这些命令的错误，见
 <a href="eval.html#catch-errors">catch-errors</a>  和  <a href="eval.html#ignore-errors">ignore-errors</a> 。


捕 获 错 误                                             <b class="vimtag"> <a name="catch-errors">catch-errors</a> </b>

如果你想捕获特定的错误，你需要把要关注的代码放到 try 块里，然后为该错误消息加
入 catch 子句。try 条件句的存在使得所有的错误被转换为例外。不会显示消息，而
 <a href="eval.html#v:errmsg">v:errmsg</a>  也不会设置。要找到 ":catch" 命令右边的模式，你需要知道错误例外的格
式。
   错误例外使用如下的格式: 
<code class="example"></code>
<code class="example">        Vim({cmdname}):{errmsg}</code>
或 
<code class="example">        Vim:{errmsg}</code>
<code class="example"></code>
<code class="special">{cmdname}</code> 是失败的命令名；第二种形式用于命令名未知的场合。<code class="special">{errmsg}</code> 是错误在
try 条件句发生时，本应产生的错误消息。它总是以大写的 "E" 开始，后面跟两或者三
位的错误号，一个冒号和一个空格。

例如:

命令 
<code class="example">        :unlet novar</code>
通常产生错误信息 
<code class="example">        E108: No such variable: "novar"</code>
它在 try 条件句里被转换为例外 
<code class="example">        Vim(unlet):E108: No such variable: "novar"</code>
<code class="example"></code>
命令 
<code class="example">        :dwim</code>
通常产生错误信息 
<code class="example">        E492: Not an editor command: dwim</code>
它在 try 条件句里被转换为例外 
<code class="example">        Vim:E492: Not an editor command: dwim</code>
<code class="example"></code>
你可以这样捕获所有的 ":unlet" 错误 
<code class="example">        :catch /^Vim(unlet):/</code>
或者这样捕获所有拼错命令名字的错误 
<code class="example">        :catch /^Vim:E492:/</code>
<code class="example"></code>
有的错误信息可能由不同的命令产生: 
<code class="example">        :function nofunc</code>
和 
<code class="example">        :delfunction nofunc</code>
都会产生错误信息 
<code class="example">        E128: Function name must start with a capital: nofunc</code>
它在 try 条件句里被分别转换为例外 
<code class="example">        Vim(function):E128: Function name must start with a capital: nofunc</code>
或 
<code class="example">        Vim(delfunction):E128: Function name must start with a capital: nofunc</code>
使用下面的模式，你可以根据其号码捕获错误，而不管产生的命令是什么: 
<code class="example">        :catch /^Vim(\a\+):E128:/</code>
<code class="example"></code>
有些命令，比如 
<code class="example">        :let x = novar</code>
产生多个错误信息，这里: 
<code class="example">        E121: Undefined variable: novar</code>
<code class="example">        E15: Invalid expression:  novar</code>
只有第一个会用做例外的值，因为它是最专门的那个 (见  <a href="eval.html#except-several-errors">except-several-errors</a> )。
所以你应该这样捕获它 
<code class="example">        :catch /^Vim(\a\+):E121:/</code>
<code class="example"></code>
你可以这样捕获所有和名字 "nofunc" 相关的错误 
<code class="example">        :catch /\&lt;nofunc\&gt;/</code>
<code class="example"></code>
你可以这样捕获 ":write" 和 ":read" 命令产生的所有 Vim 的错误 
<code class="example">        :catch /^Vim(\(write\|read\)):E\d\+:/</code>
<code class="example"></code>
你可以这样捕获所有的 Vim 错误 
<code class="example">        :catch /^Vim\((\a\+)\)\=:E\d\+:/</code>

                                                        <b class="vimtag"> <a name="catch-text">catch-text</a> </b>
<code class="note">注意</code>: 永远不要根据错误信息文本本身捕获错误: 
<code class="example">        :catch /No such variable/</code>
只适用于英语的 locale，如果用户用  <a href="mlang.html#:language">:language</a>  命令使用别的语言就不行了。不过，
在注释里引用该消息或许有帮助: 
<code class="example">        :catch /^Vim(\a\+):E108:/   " No such variable</code>
<code class="example"></code>
<code class="example"></code>
忽 略 错 误                                             <b class="vimtag"> <a name="ignore-errors">ignore-errors</a> </b>

你可以通过在本地捕获来忽略某个 Vim 命令的错误: 
<code class="example"></code>
<code class="example">        :try</code>
<code class="example">        :  write</code>
<code class="example">        :catch</code>
<code class="example">        :endtry</code>
<code class="example"></code>
但强烈建议， <code class="emphasis">不要</code> 使用这种简单的形式，因为它捕获的东西超过你的想象。":write"
命令里，会执行一些自动命令，它们可能引起与写入无关的错误。例如: 
<code class="example"></code>
<code class="example">        :au BufWritePre * unlet novar</code>
<code class="example"></code>
作为脚本的作者，你不应该负责处理这些错误: 使用你书写的脚本的用户可能定义了这些
自动命令。而你这么做只会屏蔽用户自己的错误。
   更好的方法是用 
<code class="example"></code>
<code class="example">        :try</code>
<code class="example">        :  write</code>
<code class="example">        :catch /^Vim(write):/</code>
<code class="example">        :endtry</code>
<code class="example"></code>
这样，只捕获真正的 write 错误。总之，只应该捕获你有意忽略的错误。

对于单个不会执行自动命令的命令，你可以用 ":silent!" 命令来关闭错误到例外的转
换: 
<code class="example">        :silent! nunmap k</code>
即使在活动的 try 条件句里也能这么用。


捕 获 中 断                                             <b class="vimtag"> <a name="catch-interrupt">catch-interrupt</a> </b>

如果有活动的 try 条件句，中断 (<code class="keystroke">CTRL-C</code>) 被转换为例外 "Vim:Interrupt"。你可以和
其他例外一样捕获它。那样，脚本就不会中止。
   例如: 
<code class="example"></code>
<code class="example">        :function! TASK1()</code>
<code class="example">        :  sleep 10</code>
<code class="example">        :endfunction</code>
<code class="example"></code>
<code class="example">        :function! TASK2()</code>
<code class="example">        :  sleep 20</code>
<code class="example">        :endfunction</code>
<code class="example"></code>
<code class="example">        :while 1</code>
<code class="example">        :  let command = input("Type a command: ")</code>
<code class="example">        :  try</code>
<code class="example">        :    if command == ""</code>
<code class="example">        :      continue</code>
<code class="example">        :    elseif command == "END"</code>
<code class="example">        :      break</code>
<code class="example">        :    elseif command == "TASK1"</code>
<code class="example">        :      call TASK1()</code>
<code class="example">        :    elseif command == "TASK2"</code>
<code class="example">        :      call TASK2()</code>
<code class="example">        :    else</code>
<code class="example">        :      echo "\nIllegal command:" command</code>
<code class="example">        :      continue</code>
<code class="example">        :    endif</code>
<code class="example">        :  catch /^Vim:Interrupt$/</code>
<code class="example">        :    echo "\nCommand interrupted"</code>
<code class="example">        :    " Caught the interrupt.  Continue with next prompt.</code>
<code class="example">        :  endtry</code>
<code class="example">        :endwhile</code>
<code class="example"></code>
这里，你可以用 <code class="keystroke">CTRL-C</code> 中止任务；脚本会询问新的命令。如果你在提示上按 <code class="keystroke">CTRL-C</code>，
脚本就会中止。

要测试在你脚本的某一行上如果按了 <code class="keystroke">CTRL-C</code> 会发生什么，使用调试模式，然后在那行上
执行  <a href="repeat.html#%3Equit">&gt;quit</a>  或  <a href="repeat.html#%3Einterrupt">&gt;interrupt</a> 。见  <a href="repeat.html#debug-scripts">debug-scripts</a> 。


捕 获 一 切                                             <b class="vimtag"> <a name="catch-all">catch-all</a> </b>

命令 
<code class="example"></code>
<code class="example">        :catch /.*/</code>
<code class="example">        :catch //</code>
<code class="example">        :catch</code>
<code class="example"></code>
会捕获一切: 错误例外，中断例外和  <a href="eval.html#:throw">:throw</a>  命令显式抛出的例外。脚本的顶层可用此
捕获所有意料不到的问题。
   示例: 
<code class="example"></code>
<code class="example">        :try</code>
<code class="example">        :</code>
<code class="example">        :  " 这里做重要的工作</code>
<code class="example">        :</code>
<code class="example">        :catch /MyException/</code>
<code class="example">        :</code>
<code class="example">        :  " 处理未知的问题</code>
<code class="example">        :</code>
<code class="example">        :catch /^Vim:Interrupt$/</code>
<code class="example">        :    echo "脚本被中断"</code>
<code class="example">        :catch /.*/</code>
<code class="example">        :  echo "内部错误 (" .. v:exception .. ")"</code>
<code class="example">        :  echo " - 发生在 " .. v:throwpoint</code>
<code class="example">        :endtry</code>
<code class="example">        :" 脚本结束</code>

<code class="note">注意</code>: 捕获一切可能会捕获到比你想得到的更多的错误。所以，强烈建议你只用指定模式
参数的 ":catch" 来捕获你真正处理的错误。
   例如: 捕获一切会使得按 <code class="keystroke">CTRL-C</code> 来中断脚本几乎没有办法: 
<code class="example"></code>
<code class="example">        :while 1</code>
<code class="example">        :  try</code>
<code class="example">        :    sleep 1</code>
<code class="example">        :  catch</code>
<code class="example">        :  endtry</code>
<code class="example">        :endwhile</code>
<code class="example"></code>
<code class="example"></code>
例 外 和 自 动 命 令                                    <b class="vimtag"> <a name="except-autocmd">except-autocmd</a> </b>

执行自动命令的过程中可以使用例外。例如: 
<code class="example"></code>
<code class="example">        :autocmd User x try</code>
<code class="example">        :autocmd User x   throw "Oops!"</code>
<code class="example">        :autocmd User x catch</code>
<code class="example">        :autocmd User x   echo v:exception</code>
<code class="example">        :autocmd User x endtry</code>
<code class="example">        :autocmd User x throw "Arrgh!"</code>
<code class="example">        :autocmd User x echo "Should not be displayed"</code>
<code class="example">        :</code>
<code class="example">        :try</code>
<code class="example">        :  doautocmd User x</code>
<code class="example">        :catch</code>
<code class="example">        :  echo v:exception</code>
<code class="example">        :endtry</code>
<code class="example"></code>
会显示 "Oops!" 和 "Arrgh!"。

                                                        <b class="vimtag"> <a name="except-autocmd-Pre">except-autocmd-Pre</a> </b>
有些命令里，自动命令在命令执行的主要动作之前执行。如果在自动命令的序列中抛
出没有捕获的例外，该序列和导致其执行的命令本身被放弃，而例外被传播到命令的调用
者那里。
   例如: 
<code class="example"></code>
<code class="example">        :autocmd BufWritePre * throw "FAIL"</code>
<code class="example">        :autocmd BufWritePre * echo "应该不会显示"</code>
<code class="example">        :</code>
<code class="example">        :try</code>
<code class="example">        :  write</code>
<code class="example">        :catch</code>
<code class="example">        :  echo "Caught:" v:exception "from" v:throwpoint</code>
<code class="example">        :endtry</code>
<code class="example"></code>
这里，":write" 命令不会写入当前编辑的文件 (你可以通过查看 <a href="options.html#'modified'">'modified'</a> 发现)。因
为例外来自 BufWritePre 自动命令，它放弃了 ":write"。然后，该例外被捕获而脚本会
显示: 
<code class="example"></code>
<code class="example">        Caught: FAIL from BufWrite Auto commands for "*"</code>

                                                        <b class="vimtag"> <a name="except-autocmd-Post">except-autocmd-Post</a> </b>
有些命令里，自动命令在命令执行的主要动作之后执行。如果主要动作失败，而命令包含
在活动的 try 条件句里，将跳过这些自动命令并抛出错误例外，该命令的调用者可以捕
获这些例外。
   例如: 
<code class="example"></code>
<code class="example">        :autocmd BufWritePost * echo "文件被成功写入！"</code>
<code class="example">        :</code>
<code class="example">        :try</code>
<code class="example">        :  write /i/m/p/o/s/s/i/b/l/e</code>
<code class="example">        :catch</code>
<code class="example">        :  echo v:exception</code>
<code class="example">        :endtry</code>
<code class="example"></code>
只会显示: 
<code class="example"></code>
<code class="example">        Vim(write):E212: Can't open file for writing (/i/m/p/o/s/s/i/b/l/e)</code>
<code class="example"></code>
如果你真想在主要动作失败的时候也执行自动命令的话，在 catch 子句里激活自动命令
事件。
   例如: 
<code class="example"></code>
<code class="example">        :autocmd BufWritePre  * set noreadonly</code>
<code class="example">        :autocmd BufWritePost * set readonly</code>
<code class="example">        :</code>
<code class="example">        :try</code>
<code class="example">        :  write /i/m/p/o/s/s/i/b/l/e</code>
<code class="example">        :catch</code>
<code class="example">        :  doautocmd BufWritePost /i/m/p/o/s/s/i/b/l/e</code>
<code class="example">        :endtry</code>

你也可以用 ":silent!": 
<code class="example"></code>
<code class="example">        :let x = "ok"</code>
<code class="example">        :let v:errmsg = ""</code>
<code class="example">        :autocmd BufWritePost * if v:errmsg != ""</code>
<code class="example">        :autocmd BufWritePost *   let x = "after fail"</code>
<code class="example">        :autocmd BufWritePost * endif</code>
<code class="example">        :try</code>
<code class="example">        :  silent! write /i/m/p/o/s/s/i/b/l/e</code>
<code class="example">        :catch</code>
<code class="example">        :endtry</code>
<code class="example">        :echo x</code>
<code class="example"></code>
会显示 "after fail"。

如果命令的主要动作没有失败，可以在命令的调用者那里捕获自动命令产生的例外: 
<code class="example"></code>
<code class="example">        :autocmd BufWritePost * throw ":-("</code>
<code class="example">        :autocmd BufWritePost * echo "这里不应该被显示"</code>
<code class="example">        :</code>
<code class="example">        :try</code>
<code class="example">        :  write</code>
<code class="example">        :catch</code>
<code class="example">        :  echo v:exception</code>
<code class="example">        :endtry</code>

                                                        <b class="vimtag"> <a name="except-autocmd-Cmd">except-autocmd-Cmd</a> </b>
有的命令的正常动作可以被自动命令的序列代替。可以在命令的调用者那里捕获该序列产
生的例外。
   例如: 对于 ":write" 命令，调用者并不知道发生例外时，文件是不是已经被写入。
你需要想办法告知调用者。 
<code class="example"></code>
<code class="example">        :if !exists("cnt")</code>
<code class="example">        :  let cnt = 0</code>
<code class="example">        :</code>
<code class="example">        :  autocmd BufWriteCmd * if &amp;modified</code>
<code class="example">        :  autocmd BufWriteCmd *   let cnt = cnt + 1</code>
<code class="example">        :  autocmd BufWriteCmd *   if cnt % 3 == 2</code>
<code class="example">        :  autocmd BufWriteCmd *     throw "BufWriteCmdError"</code>
<code class="example">        :  autocmd BufWriteCmd *   endif</code>
<code class="example">        :  autocmd BufWriteCmd *   write | set nomodified</code>
<code class="example">        :  autocmd BufWriteCmd *   if cnt % 3 == 0</code>
<code class="example">        :  autocmd BufWriteCmd *     throw "BufWriteCmdError"</code>
<code class="example">        :  autocmd BufWriteCmd *   endif</code>
<code class="example">        :  autocmd BufWriteCmd *   echo "File successfully written!"</code>
<code class="example">        :  autocmd BufWriteCmd * endif</code>
<code class="example">        :endif</code>
<code class="example">        :</code>
<code class="example">        :try</code>
<code class="example">        :       write</code>
<code class="example">        :catch /^BufWriteCmdError$/</code>
<code class="example">        :  if &amp;modified</code>
<code class="example">        :    echo "Error on writing (file contents not changed)"</code>
<code class="example">        :  else</code>
<code class="example">        :    echo "Error after writing"</code>
<code class="example">        :  endif</code>
<code class="example">        :catch /^Vim(write):/</code>
<code class="example">        :    echo "Error on writing"</code>
<code class="example">        :endtry</code>
<code class="example"></code>
如果脚本在修改后执行了多次，它先显示 
<code class="example">        File successfully written!</code>
然后 
<code class="example">        Error on writing (file contents not changed)</code>
然后 
<code class="example">        Error after writing</code>
等等。

                                                        <b class="vimtag"> <a name="except-autocmd-ill">except-autocmd-ill</a> </b>
你不能把一个 try 条件句分散到不同事件的自动命令。
下面的代码是非法的构造: 
<code class="example"></code>
<code class="example">        :autocmd BufWritePre  * try</code>
<code class="example">        :</code>
<code class="example">        :autocmd BufWritePost * catch</code>
<code class="example">        :autocmd BufWritePost *   echo v:exception</code>
<code class="example">        :autocmd BufWritePost * endtry</code>
<code class="example">        :</code>
<code class="example">        :write</code>
<code class="example"></code>
<code class="example"></code>
例 外 层 次 和 参 数 化 的 例 外                        <b class="vimtag"> <a name="except-hier-param">except-hier-param</a> </b>

有些编程语言支持使用例外类的层次结构，或者在例外类的对象里传入附加的信息。你可
以在 Vim 里完成类似的工作。
   为了抛出属于某层次的例外，只要抛出完整的类名，部件之间用冒号分隔。比如，在
某个数学库里的溢出错误可以抛出字符串 "EXCEPT:MATHERR:OVERFLOW"。
   如果你想给例外类传递附加的信息，把它加到括号里。比如写入文件 "myfile" 时的
错误，可以抛出字符串 "EXCEPT:IO:WRITEERR(myfile)"。
   在 ":catch" 命令里使用合适的模式，可以捕获你的层次中的基本类或者派生类。括
号里的附加信息也可以运用 ":substitute" 命令从  <a href="eval.html#v:exception">v:exception</a>  里切出。
   例如: 
<code class="example"></code>
<code class="example">        :function! CheckRange(a, func)</code>
<code class="example">        :  if a:a &lt; 0</code>
<code class="example">        :    throw "EXCEPT:MATHERR:RANGE(" .. a:func .. ")"</code>
<code class="example">        :  endif</code>
<code class="example">        :endfunction</code>
<code class="example">        :</code>
<code class="example">        :function! Add(a, b)</code>
<code class="example">        :  call CheckRange(a:a, "Add")</code>
<code class="example">        :  call CheckRange(a:b, "Add")</code>
<code class="example">        :  let c = a:a + a:b</code>
<code class="example">        :  if c &lt; 0</code>
<code class="example">        :    throw "EXCEPT:MATHERR:OVERFLOW"</code>
<code class="example">        :  endif</code>
<code class="example">        :  return c</code>
<code class="example">        :endfunction</code>
<code class="example">        :</code>
<code class="example">        :function! Div(a, b)</code>
<code class="example">        :  call CheckRange(a:a, "Div")</code>
<code class="example">        :  call CheckRange(a:b, "Div")</code>
<code class="example">        :  if (a:b == 0)</code>
<code class="example">        :    throw "EXCEPT:MATHERR:ZERODIV"</code>
<code class="example">        :  endif</code>
<code class="example">        :  return a:a / a:b</code>
<code class="example">        :endfunction</code>
<code class="example">        :</code>
<code class="example">        :function! Write(file)</code>
<code class="example">        :  try</code>
<code class="example">        :    execute "write" fnameescape(a:file)</code>
<code class="example">        :  catch /^Vim(write):/</code>
<code class="example">        :    throw "EXCEPT:IO(" .. getcwd() .. ", " .. a:file .. "):WRITEERR"</code>
<code class="example">        :  endtry</code>
<code class="example">        :endfunction</code>
<code class="example">        :</code>
<code class="example">        :try</code>
<code class="example">        :</code>
<code class="example">        :  " 一些算术和 I/O</code>
<code class="example">        :</code>
<code class="example">        :catch /^EXCEPT:MATHERR:RANGE/</code>
<code class="example">        :  let function = substitute(v:exception, '.*(\(\a\+\)).*', '\1', "")</code>
<code class="example">        :  echo "Range error in" function</code>
<code class="example">        :</code>
<code class="example">        :catch /^EXCEPT:MATHERR/        " 捕获 OVERFLOW 和 ZERODIV</code>
<code class="example">        :  echo "Math error"</code>
<code class="example">        :</code>
<code class="example">        :catch /^EXCEPT:IO/</code>
<code class="example">        :  let dir = substitute(v:exception, '.*(\(.\+\),\s*.\+).*', '\1', "")</code>
<code class="example">        :  let file = substitute(v:exception, '.*(.\+,\s*\(.\+\)).*', '\1', "")</code>
<code class="example">        :  if file !~ '^/'</code>
<code class="example">        :    let file = dir .. "/" .. file</code>
<code class="example">        :  endif</code>
<code class="example">        :  echo 'I/O error for "' .. file .. '"'</code>
<code class="example">        :</code>
<code class="example">        :catch /^EXCEPT/</code>
<code class="example">        :  echo "Unspecified error"</code>
<code class="example">        :</code>
<code class="example">        :endtry</code>
<code class="example"></code>
Vim 自己抛出的例外 (错误或者按了 <code class="keystroke">CTRL-C</code>) 使用扁平的层次: 它们都在 "Vim" 类里。
你自己不能抛出带有 "Vim" 前缀的例外；它们是 Vim 保留的。
   如果已知失败的命令名，Vim 错误例外使用该命令名作为参数。见  <a href="eval.html#catch-errors">catch-errors</a> 。


特 别 之 处
                                                        <b class="vimtag"> <a name="except-compat">except-compat</a> </b>
例外处理的概念需要产生例外的命令序列被立即中止，而控制转移到 finally 子句和/或
catch 子句。

在 Vim 脚本语言里，有一些情况下脚本和函数在错误后还会继续: 在没有 "abort" 标志
位的函数或者 ":silent!" 之后的命令里，控制流转到下一行。而在函数外，控制流转到
最外层 ":endwhile" 或者 ":endif" 之后的行。另一方面，错误应该可以作为例外被捕
获 (因而，需要立即被中止)。

这个问题的解决方法是把仅在有活动 try 条件句的时候，把错误转化为例外，并立即中
止 (如果没有用 ":silent!" 抑制的话)。这不是一个限制，因为 (错误) 例外只能在活
动的 try 条件句里被捕获。如果你需要立即终止而不需要捕获错误的话，只要用一个没
有 catch 子句的 try 子句就可以了 (你可以用 finally 子句指定终止前执行的清理代
码。)

如果没有活动的 try 条件句，使用通常的中止和继续行为，而不是立即中止。这样，保
证了与 Vim 6.1 和之前版本编写的脚本的兼容性。

不过，如果在活动的 try 条件句里执行已有的不使用例外处理命令的脚本 (或者调用它
的一个函数)，你也许会改变已有脚本发生错误时的控制流。你会在错误时立即中止并且
在新的脚本里捕获错误。如果被执行的脚本通过 ":silent!" 命令抑制了错误 (在合适的
时候测试  <a href="eval.html#v:errmsg">v:errmsg</a>  来检查错误)，它的执行路径没有改变。错误也不会转换为例外。
(见  <a href="various.html#:silent">:silent</a> 。) 所以唯一留下的可能是不关心错误并产生错误信息的脚本。可能，你
也不希望在新的脚本里使用这样的代码吧。

                                                        <b class="vimtag"> <a name="except-syntax-err">except-syntax-err</a> </b>
例外处理命令的语法错误永远不会被它所属的 try 条件句的任何 ":catch" 命令所捕
获。不过，还是会执行它的 finally 子句。
   例如: 
<code class="example"></code>
<code class="example">        :try</code>
<code class="example">        :  try</code>
<code class="example">        :    throw 4711</code>
<code class="example">        :  catch /\(/ " 有语法错误</code>
<code class="example">        :    echo "in catch with syntax error"</code>
<code class="example">        :  catch</code>
<code class="example">        :    echo "inner catch-all"</code>
<code class="example">        :  finally</code>
<code class="example">        :    echo "inner finally"</code>
<code class="example">        :  endtry</code>
<code class="example">        :catch</code>
<code class="example">        :  echo 'outer catch-all caught "' .. v:exception .. '"'</code>
<code class="example">        :  finally</code>
<code class="example">        :    echo "outer finally"</code>
<code class="example">        :endtry</code>
<code class="example"></code>
会显示: 
<code class="example">    inner finally</code>
<code class="example">    outer catch-all caught "Vim(catch):E54: Unmatched \("</code>
<code class="example">    outer finally</code>
原来的例外被丢弃了，抛出的是取而代之的语法错误的错误例外。

                                                        <b class="vimtag"> <a name="except-single-line">except-single-line</a> </b>
":try"、":catch"、":finally" 和 ":endtry" 命令可以放在一行里，但这样如果有语法
错误，可能使得 "catch" 行无法被识别。所以，最好不要这么做。
   例如: 
<code class="example">        :try | unlet! foo # | catch | endtry</code>
":unlet!" 参数之后的拖尾字符抛出了错误例外，但因此无法看到 ":catch" 和
":endtry" 命令，从而只能丢弃该错误例外并且显示消息 "E488: Trailing
characters"。

                                                        <b class="vimtag"> <a name="except-several-errors">except-several-errors</a> </b>
如果多个错误在一个命令里出现，第一个错误信息通常是最专门的，因而它被转换为错误
例外。
   例如: 
<code class="example">        echo novar</code>
产生 
<code class="example">        E121: Undefined variable: novar</code>
<code class="example">        E15: Invalid expression: novar</code>
try 条件句里错误例外的值是: 
<code class="example">        Vim(echo):E121: Undefined variable: novar</code>
                                                        <b class="vimtag"> <a name="except-syntax-error">except-syntax-error</a> </b>
不过，如果同一命令在普通错误之后发现了语法错误，语法错误被用作抛出的例外。
   例如: 
<code class="example">        unlet novar #</code>
产生 
<code class="example">        E108: No such variable: "novar"</code>
<code class="example">        E488: Trailing characters</code>
try 条件句里错误例外的值是: 
<code class="example">        Vim(unlet):E488: Trailing characters</code>
这么做是因为语法错误可能会以用户意想不到的方式改变执行的路径。例如: 
<code class="example">        try</code>
<code class="example">            try | unlet novar # | catch | echo v:exception | endtry</code>
<code class="example">        catch /.*/</code>
<code class="example">            echo "outer catch:" v:exception</code>
<code class="example">        endtry</code>
显示 "outer catch: Vim(unlet):E488: Trailing characters"，然后给出错误信息
"E600: Missing :endtry"，见  <a href="eval.html#except-single-line">except-single-line</a> 。

</section><hr class="doubleline" /><section class=inner>
<h4>9. 示例                                                 <b class="vimtag"> <a name="eval-examples">eval-examples</a> </b></h4>
<code class="section">用二进制显示 </code>

<code class="example">  :" 函数 Nr2Bin() 返回数值的二进制字符串。</code>
<code class="example">  :func Nr2Bin(nr)</code>
<code class="example">  :  let n = a:nr</code>
<code class="example">  :  let r = ""</code>
<code class="example">  :  while n</code>
<code class="example">  :    let r = '01'[n % 2] .. r</code>
<code class="example">  :    let n = n / 2</code>
<code class="example">  :  endwhile</code>
<code class="example">  :  return r</code>
<code class="example">  :endfunc</code>
<code class="example"></code>
<code class="example">  :" 函数 String2Hex() 把字符串里的每个字符转换成二进制字符串，用连字符分隔字</code>
<code class="example">  :" 符。</code>
<code class="example">  :func String2Bin(str)</code>
<code class="example">  :  let out = ''</code>
<code class="example">  :  for ix in range(strlen(a:str))</code>
<code class="example">  :    let out = out .. '-' .. Nr2Bin(char2nr(a:str[ix]))</code>
<code class="example">  :  endfor</code>
<code class="example">  :  return out[1:]</code>
<code class="example">  :endfunc</code>
<code class="example"></code>
使用示例: 
<code class="example">  :echo Nr2Bin(32)</code>
返回: "100000" 
<code class="example">  :echo String2Bin("32")</code>
返回: "110011-110010"


<code class="section">给行排序 </code>

下例用特定比较函数给行排序。 
<code class="example"></code>
<code class="example">  :func SortBuffer()</code>
<code class="example">  :  let lines = getline(1, '$')</code>
<code class="example">  :  call sort(lines, function("Strcmp"))</code>
<code class="example">  :  call setline(1, lines)</code>
<code class="example">  :endfunction</code>
<code class="example"></code>
可写为一行程序: 
<code class="example">  :call setline(1, sort(getline(1, '$'), function("Strcmp")))</code>
<code class="example"></code>
<code class="example"></code>
<code class="section">scanf() 的替代 </code>
                                                        <b class="vimtag"> <a name="sscanf">sscanf</a> </b>
Vim 里没有 sscanf() 函数。如果你需要提取一行的部分内容，可以使用 matchstr() 和
substitute() 完成。本例子说明如何得到从类似 "foobar.txt, 123, 45" 的行里提取文
件名，行号和列号。 
<code class="example">   :" 设置匹配模式</code>
<code class="example">   :let mx='\(\f\+\),\s*\(\d\+\),\s*\(\d\+\)'</code>
<code class="example">   :"取得匹配整个表达式的文本部分</code>
<code class="example">   :let l = matchstr(line, mx)</code>
<code class="example">   :"从匹配中提取每个项目</code>
<code class="example">   :let file = substitute(l, mx, '\1', '')</code>
<code class="example">   :let lnum = substitute(l, mx, '\2', '')</code>
<code class="example">   :let col = substitute(l, mx, '\3', '')</code>
<code class="example"></code>
这里，输入是变量 "line"，返回值放在变量 "file"、"lnum" 和 "col" 里。(Michael
Geddes 提供的方法)


<code class="section">输出 scriptnames 到字典 </code>
                                                <b class="vimtag"> <a name="scriptnames-dictionary">scriptnames-dictionary</a> </b>
 <a href="repeat.html#:scriptnames">:scriptnames</a>  命令可用于得到执行过的所有脚本文件的列表。没有等价的函数或变量
(因为很少用到)。如果需要操作此列表，可以使用下面的代码: 
<code class="example">    " 把 ":scriptnames" 的输出存放到 scriptnames_output 变量中。</code>
<code class="example">    let scriptnames_output = ''</code>
<code class="example">    redir =&gt; scriptnames_output</code>
<code class="example">    silent scriptnames</code>
<code class="example">    redir END</code>
<code class="example"></code>
<code class="example">    " 把输出分拆为行，并对每行进行分析。在 "script" 字典中加入项目。</code>
<code class="example">    let scripts = {}</code>
<code class="example">    for line in split(scriptnames_output, "\n")</code>
<code class="example">      " 只处理非空白行。</code>
<code class="example">      if line =~ '\S'</code>
<code class="example">        " 获取每行的第一个数字。</code>
<code class="example">        let nr = matchstr(line, '\d\+')</code>
<code class="example">        " 获取文件名，删除脚本号 " 123: "。</code>
<code class="example">        let name = substitute(line, '.\+:\s*', '', '')</code>
<code class="example">        " 在字典中加入项目</code>
<code class="example">        let scripts[nr] = name</code>
<code class="example">      endif</code>
<code class="example">    endfor</code>
<code class="example">    unlet scriptnames_output</code>
<code class="example"></code>
</section><hr class="doubleline" /><section class=inner>
<h4>10. Vim script versions         <b class="vimtag"> <a name="vimscript-version">vimscript-version</a> </b> <b class="vimtag"> <a name="vimscript-versions">vimscript-versions</a> </b></h4>                                                        <b class="vimtag"> <a name="scriptversion">scriptversion</a> </b>
随着时间推移，Vim 脚本加入很多新特性。这包括了 Ex 命令、函数、变量类型等等。每
个单独的特性都可以用  <a href="builtin.html#has()">has()</a>  和  <a href="builtin.html#exists()">exists()</a>  函数检查。

有时旧功能的语法阻碍了 Vim 的改进。而撤销相关支持又会破坏旧的 Vim 脚本。为此，
可用显式的  <a href="repeat.html#:scriptversion">:scriptversion</a>  命令。当 Vim 脚本和旧版本的 Vim 不兼容时，会显式地
报错，而不会出现各种奇怪的失败。

在  <a href="vim9.html#Vim9">Vim9</a>  脚本里使用  <a href="userfunc.html#:function">:function</a>  定义的老式函数时，使用 scriptversion 4。

                                                        <b class="vimtag"> <a name="scriptversion-1">scriptversion-1</a> </b>  
<code class="example"> :scriptversion 1</code>
        这是原本的 Vim 脚本，和不使用  <a href="repeat.html#:scriptversion">:scriptversion</a>  命令一样。可用于把一段
        代码回到旧语法。这样测试是否支持: 
<code class="example">                has('vimscript-1')</code>
<code class="example"></code>
                                                        <b class="vimtag"> <a name="scriptversion-2">scriptversion-2</a> </b>  
<code class="example"> :scriptversion 2</code>
        不支持用 "." 进行字符串连接，而用 ".." 代替。
        这避免了字典成员访问和浮点数的二义性。现在 ".5" 意味着数值 0.5。

                                                        <b class="vimtag"> <a name="scriptversion-3">scriptversion-3</a> </b>  
<code class="example"> :scriptversion 3</code>
        所有的  <a href="eval.html#vim-variable">vim-variable</a>  必须使用 "v:" 前缀。例如 "version" 不再用作
         <a href="eval.html#v:version">v:version</a>  的简称，而可以用作正常变量。
        同样适用于一些显而易见的名字，如 "count" 等等。

        这样测试是否支持: 
<code class="example">                has('vimscript-3')</code>

                                                        <b class="vimtag"> <a name="scriptversion-4">scriptversion-4</a> </b>  
<code class="example"> :scriptversion 4</code>
        不把零开始的数值识别为八进制。"0o" 或 "0O" 开始的还是能识别为八进制。
        在之前的版本中你会看到: 
<code class="example">                echo 017   " 显示 15 (八进制)</code>
<code class="example">                echo 0o17  " 显示 15 (八进制)</code>
<code class="example">                echo 018   " 显示 18 (十进制)</code>
        使用脚本版本 4 后: 
<code class="example">                echo 017   " 显示 17 (十进制)</code>
<code class="example">                echo 0o17  " 显示 15 (八进制)</code>
<code class="example">                echo 018   " 显示 18 (十进制)</code>
        同时，可以在数值内部使用单引号来提高可读性: 
<code class="example">                echo 1'000'000</code>
        引号必须在数位之间。

        这样测试是否支持: 
<code class="example">                has('vimscript-4')</code>
<code class="example"></code>
</section><hr class="doubleline" /><section class=inner>
<h4>11. 不包含 +eval 特性                           <b class="vimtag"> <a name="no-eval-feature">no-eval-feature</a> </b></h4>
如果编译时关闭了  <a href="various.html#+eval">+eval</a>  特性，以上的表达式计算命令都不可用。为了避免因此导致
你的 Vim 脚本产生各种错误，":if" 和 ":endif" 命令仍然得到识别。不过 ":if" 的参
数和一切 ":if" 和匹配的 ":endif" 之间的内容都被忽略。可以嵌套 ":if" 块，但只允
许出现在行首。不识别 ":else" 命令。

下例演示如何在不存在  <a href="various.html#+eval">+eval</a>  特性时不执行命令: 
<code class="example"></code>
<code class="example">        :if 1</code>
<code class="example">        :  echo "编译加入了表达式求值"</code>
<code class="example">        :else</code>
<code class="example">        :  echo "你_永远_看不到这条消息"</code>
<code class="example">        :endif</code>
<code class="example"></code>
要在  <a href="various.html#+eval">+eval</a>  特性关闭时才执行命令有两种方法。最简单的是提前退出脚本 (或
Vim): 
<code class="example">        if 1</code>
<code class="example">           echo "带 +eval 执行的命令"</code>
<code class="example">           finish</code>
<code class="example">        endif</code>
<code class="example">        args  " 不带 +eval 执行的命令</code>
<code class="example"></code>
如果不想中止脚本的载入可以用一些小技巧，如下例所示: 
<code class="example"></code>
<code class="example">        silent! while 0</code>
<code class="example">          set history=111</code>
<code class="example">        silent! endwhile</code>
<code class="example"></code>
 <a href="various.html#+eval">+eval</a>  特性可用时，因为 "while 0" 跳过此命令。没有  <a href="various.html#+eval">+eval</a>  特性时，"while 0"
是错误但被安静地忽略，从而执行此命令。

</section><hr class="doubleline" /><section class=inner>
<h4>12. 沙盘 (sandbox)                              <b class="vimtag"> <a name="eval-sandbox">eval-sandbox</a> </b> <b class="vimtag"> <a name="sandbox">sandbox</a> </b></h4>
<a href="options.html#'foldexpr'">'foldexpr'</a>、<a href="options.html#'formatexpr'">'formatexpr'</a>、<a href="options.html#'includeexpr'">'includeexpr'</a>、<a href="options.html#'indentexpr'">'indentexpr'</a>、<a href="options.html#'statusline'">'statusline'</a> 和
<a href="options.html#'foldtext'">'foldtext'</a> 选项在沙盘 (sandbox) 里进行计算。这意味着这些表达式不会产生可怕的副
作用。在模式行上设置这些选项时，以及在标签文件里和命令行上的 <code class="keystroke">CTRL-R</code> = 执行命令
时，这项措施提供了一定的安全性。
沙盘也用于  <a href="eval.html#:sandbox">:sandbox</a>  命令。
                                                                <b class="vimtag"> <a name="E48">E48</a> </b>
沙盘里，不允许以下操作:
        - 修改缓冲区文本
        - 定义或者改变映射、自动命令和用户命令
        - 设置若干选项 (见  <a href="options.html#option-summary">option-summary</a> )
        - 设置若干 v: 变量 (见  <a href="eval.html#v:var">v:var</a> )  <b class="vimtag"> <a name="E794">E794</a> </b>
        - 执行外壳命令
        - 读入或者写到文件
        - 跳转到另一缓冲区或者去编辑文件
        - 执行 Python、Perl 等命令
这并不能保证 100% 安全，但应该可以挡住大多数攻击。

                                                        <b class="vimtag"> <a name=":san">:san</a> </b> <b class="vimtag"> <a name=":sandbox">:sandbox</a> </b>
:san[dbox] <code class="special">{cmd}</code>        在沙盘里执行 <code class="special">{cmd}</code>。用于计算可能在模式行里设置的选项，
                        比如 <a href="options.html#'foldexpr'">'foldexpr'</a>。

                                                        <b class="vimtag"> <a name="sandbox-option">sandbox-option</a> </b>
一些选项包含表达式。对这些表达式进行计算时可能要使用沙盘才能避免安全性的威胁。
但沙盘限制较多，所以只有在从不安全的位置设置选项时才会如此。在此上下文中，不安
全的位置指:
- 执行当前目录的 .vimrc 或 .exrc 时
- 在沙盘里执行时
- 来自模式行的值
- 执行沙盘里定义的函数时

<code class="note">注意</code> 如果在沙盘里保存选项值然后恢复之，该选项仍然标记为在沙盘里设置。

</section><hr class="doubleline" /><section class=inner>
<h4>13. 文本锁                                                      <b class="vimtag"> <a name="textlock">textlock</a> </b></h4>
在一些情况下，不允许修改缓冲区里的文本、跳转到其它窗口和一些其它会引起混淆或打
断 Vim 正在进行的操作的动作。这主要适用于和 Vim 实际正在进行其它操作的同时发生
的事情。例如，<a href="options.html#'balloonexpr'">'balloonexpr'</a> 的计算可能发生在鼠标指针定位在若干位置的任何时候。

文本锁激活时，不允许:
        - 修改缓冲区文本
        - 跳转到其它缓冲区或窗口
        - 编辑其它文件
        - 关闭窗口或者退出 Vim
        - 其它

 vim:tw=78:ts=8:noet:ft=help:norl:
</section>
</article>
<footer>
Generated by vim2html
</footer>
</body>
</html>
